From abc76c6b5b3e2eabd3fd3ceb96ffe02979dc8956 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Wed, 11 Jun 2025 08:28:31 +0000 Subject: [PATCH 001/213] 8359126: [AIX] new test TestImplicitNullChecks.java fails Reviewed-by: rcastanedalo, dbriemann --- .../jtreg/compiler/gcbarriers/TestImplicitNullChecks.java | 5 ++++- .../compiler/lib/ir_framework/test/IREncodingPrinter.java | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/gcbarriers/TestImplicitNullChecks.java b/test/hotspot/jtreg/compiler/gcbarriers/TestImplicitNullChecks.java index a77a51312de..34583b8fea9 100644 --- a/test/hotspot/jtreg/compiler/gcbarriers/TestImplicitNullChecks.java +++ b/test/hotspot/jtreg/compiler/gcbarriers/TestImplicitNullChecks.java @@ -67,7 +67,10 @@ public static void main(String[] args) { } @Test - @IR(applyIfOr = {"UseZGC", "true", "UseG1GC", "true"}, + // On AIX, implicit null checks are limited because the zero page is + // readable (but not writable). See os::zero_page_read_protected(). + @IR(applyIfPlatform = {"aix", "false"}, + applyIfOr = {"UseZGC", "true", "UseG1GC", "true"}, counts = {IRNode.NULL_CHECK, "1"}, phase = CompilePhase.FINAL_CODE) static Object testLoad(Outer o) { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java index 4ad95ab786f..eef9998ebf8 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java @@ -62,6 +62,7 @@ public class IREncodingPrinter { // as adding non-existent platforms can lead to skipped tests. private static final List irTestingPlatforms = new ArrayList(Arrays.asList( // os.family + "aix", "linux", "mac", "windows", @@ -346,7 +347,9 @@ private boolean checkPlatform(String platform, String value) { } String os = ""; - if (Platform.isLinux()) { + if (Platform.isAix()) { + os = "aix"; + } else if (Platform.isLinux()) { os = "linux"; } else if (Platform.isOSX()) { os = "mac"; From 56ce70c5dfe1ecaf371d462d4198765d4a86db3c Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Wed, 11 Jun 2025 08:28:48 +0000 Subject: [PATCH 002/213] 8359165: AIX build broken after 8358799 Reviewed-by: kbarrett, jkern --- src/hotspot/os/posix/os_posix.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 68bdec3875c..303e44eadcb 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -59,6 +59,7 @@ #ifdef AIX #include "loadlib_aix.hpp" #include "os_aix.hpp" +#include "porting_aix.hpp" #endif #ifdef LINUX #include "os_linux.hpp" @@ -1076,7 +1077,7 @@ void os::jvm_path(char *buf, jint buflen) { return; } - char* fname; + const char* fname; #ifdef AIX Dl_info dlinfo; int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo); @@ -1099,7 +1100,7 @@ void os::jvm_path(char *buf, jint buflen) { #endif // AIX char* rp = nullptr; if (fname[0] != '\0') { - rp = os::realpath(dli_fname, buf, buflen); + rp = os::realpath(fname, buf, buflen); } if (rp == nullptr) { return; @@ -1137,7 +1138,7 @@ void os::jvm_path(char *buf, jint buflen) { "buf has been truncated"); } else { // Go back to path of .so - rp = os::realpath(dli_fname, buf, buflen); + rp = os::realpath(fname, buf, buflen); if (rp == nullptr) { return; } From 5ae32c4c86916120d2a337be9765cb6e14f3f443 Mon Sep 17 00:00:00 2001 From: Khalid Boulanouare Date: Wed, 11 Jun 2025 10:25:28 +0000 Subject: [PATCH 003/213] 8352149: Test java/awt/Frame/MultiScreenTest.java fails: Window list is empty Reviewed-by: aivanov, abhiscxk --- test/jdk/java/awt/Frame/MultiScreenTest.java | 637 ++++++++++--------- 1 file changed, 325 insertions(+), 312 deletions(-) diff --git a/test/jdk/java/awt/Frame/MultiScreenTest.java b/test/jdk/java/awt/Frame/MultiScreenTest.java index 845f601138b..cbd781f94dd 100644 --- a/test/jdk/java/awt/Frame/MultiScreenTest.java +++ b/test/jdk/java/awt/Frame/MultiScreenTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ import java.awt.RenderingHints; import java.awt.TextField; +import java.awt.Window; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; @@ -74,7 +75,7 @@ public static void main(String[] args) throws Exception { ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); gs = ge.getScreenDevices(); if (gs.length < 2) { - throw new SkippedException("You have only one monitor in your system - test passed"); + throw new SkippedException("You have only one monitor in your system"); } MultiScreenTest obj = new MultiScreenTest(); String INSTRUCTIONS = @@ -82,38 +83,42 @@ public static void main(String[] args) throws Exception { "You have " + gs.length + " monitors in your system.\n" + "Actively drag the DitherTest frames on the secondary screen and " + "if you see garbage appearing on your primary screen " + - "test failed otherwise it passed.";; + "test failed otherwise it passed."; PassFailJFrame.builder() - .title("MultiScreenTest Instruction") .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 2) .columns(40) .testUI(obj::init) + .positionTestUI(MultiScreenTest::positionTestWindows) .build() .awaitAndCheck(); } + private static void positionTestWindows(List windows, PassFailJFrame.InstructionUI instructionUI) { + // Do nothing - the location of each window is set when they're created + } + public List init() { List list = new ArrayList<>(); for (int j = 0; j < gs.length; j++) { GraphicsConfiguration[] gc = gs[j].getConfigurations(); if (gc.length > 0) { - for (int i = 0; i < gc.length / 2; i++) { - JFrame f = new JFrame(gc[i]); //test JFrame( gc ) - GCCanvas c = new GCCanvas(gc[i]);//test canvas( gc ) - Rectangle gcBounds = gc[i].getBounds(); //test getBounds() + for (int i = 0; i < gc.length && i < 10; i++) { + JFrame f = new JFrame(gc[i]); + GCCanvas c = new GCCanvas(gc[i]); + Rectangle gcBounds = gc[i].getBounds(); int xoffs = gcBounds.x; int yoffs = gcBounds.y; f.getContentPane().add(c); - f.setTitle("Screen# " + Integer.toString(j) + ", GC#" + Integer.toString(i)); + f.setTitle("Screen# " + j + ", GC#" + i); f.setSize(300, 200); - f.setLocation(400 + xoffs, (i * 150) + yoffs);//test displaying in right location + // test displaying in right location + f.setLocation(400 + xoffs, (i * 150) + yoffs); list.add(f); - Frame ditherfs = new Frame("DitherTest GC#" + Integer.toString(i), gc[i]); - ditherfs.setLayout(new BorderLayout()); //showDitherTest + Frame ditherfs = new Frame("DitherTest GC#" + i, gc[i]); + ditherfs.setLayout(new BorderLayout()); DitherTest ditherTest = new DitherTest(gc[i]); ditherfs.add("Center", ditherTest); ditherfs.setBounds(300, 200, 300, 200); @@ -126,360 +131,368 @@ public List init() { } return list; } -} - -class GCCanvas extends Canvas { - - GraphicsConfiguration gc; - Rectangle bounds; - Graphics g = this.getGraphics(); - Dimension size = getSize(); - - public GCCanvas(GraphicsConfiguration gc) { - super(gc); - this.gc = gc; - bounds = gc.getBounds(); - } - - public void paint( Graphics _g ) { - Graphics2D g = (Graphics2D) _g; - g.drawRect(0, 0, size.width-1, size.height-1); - g.setColor(Color.lightGray); - g.draw3DRect(1, 1, size.width-3, size.height-3, true); + static class GCCanvas extends Canvas { - g.setColor(Color.red); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + GraphicsConfiguration gc; + Rectangle bounds; + Dimension size = getSize(); - g.drawString("HELLO!", 110, 10); + public GCCanvas(GraphicsConfiguration gc) { + super(gc); + this.gc = gc; + bounds = gc.getBounds(); + } - g.setColor(Color.blue); - g.drawString("ScreenSize="+Integer.toString(bounds.width)+"X"+ - Integer.toString(bounds.height), 10, 20); - g.setColor(Color.green); - g.drawString(gc.toString(), 10, 30); - g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + @Override + public void paint( Graphics _g ) { - g.setColor(Color.orange); - g.fillRect(40, 20, 50, 50); + Graphics2D g = (Graphics2D) _g; - g.setColor(Color.red); - g.drawRect(100, 20, 30, 30); + g.drawRect(0, 0, size.width-1, size.height-1); + g.setColor(Color.lightGray); + g.draw3DRect(1, 1, size.width-3, size.height-3, true); - g.setColor(Color.gray); - g.drawLine(220, 20, 280, 40); + g.setColor(Color.red); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g.setColor(Color.cyan); - g.fillArc(150, 30, 30, 30, 0, 200); - } + g.drawString("HELLO!", 110, 10); - public Dimension getPreferredSize(){ - return new Dimension(300, 200); - } -} + g.setColor(Color.blue); + g.drawString("ScreenSize="+Integer.toString(bounds.width)+"X"+ + Integer.toString(bounds.height), 10, 20); + g.setColor(Color.green); + g.drawString(gc.toString(), 10, 30); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); -class DitherCanvas extends Canvas { - Image img; - static String calcString = "Calculating..."; + g.setColor(Color.orange); + g.fillRect(40, 20, 50, 50); - GraphicsConfiguration mGC; + g.setColor(Color.red); + g.drawRect(100, 20, 30, 30); - public DitherCanvas(GraphicsConfiguration gc) { - super(gc); - mGC = gc; - } + g.setColor(Color.gray); + g.drawLine(220, 20, 280, 40); - public GraphicsConfiguration getGraphicsConfig() { - return mGC; - } + g.setColor(Color.cyan); + g.fillArc(150, 30, 30, 30, 0, 200); + } - public void paint(Graphics g) { - int w = getSize().width; - int h = getSize().height; - if (img == null) { - super.paint(g); - g.setColor(Color.black); - FontMetrics fm = g.getFontMetrics(); - int x = (w - fm.stringWidth(calcString)) / 2; - int y = h / 2; - g.drawString(calcString, x, y); - } else { - g.drawImage(img, 0, 0, w, h, this); + @Override + public Dimension getPreferredSize(){ + return new Dimension(300, 200); } } - public void update(Graphics g) { - paint(g); - } + static class DitherCanvas extends Canvas { + Image img; + static String calcString = "Calculating..."; - public Dimension getMinimumSize() { - return new Dimension(20, 20); - } + GraphicsConfiguration mGC; - public Dimension getPreferredSize() { - return new Dimension(200, 200); - } + public DitherCanvas(GraphicsConfiguration gc) { + super(gc); + mGC = gc; + } - public Image getImage() { - return img; - } + public GraphicsConfiguration getGraphicsConfig() { + return mGC; + } - public void setImage(Image img) { - this.img = img; - paint(getGraphics()); - } -} + @Override + public void paint(Graphics g) { + int w = getSize().width; + int h = getSize().height; + if (img == null) { + super.paint(g); + g.setColor(Color.black); + FontMetrics fm = g.getFontMetrics(); + int x = (w - fm.stringWidth(calcString)) / 2; + int y = h / 2; + g.drawString(calcString, x, y); + } else { + g.drawImage(img, 0, 0, w, h, this); + } + } -class DitherTest extends Panel implements Runnable { - final static int NOOP = 0; - final static int RED = 1; - final static int GREEN = 2; - final static int BLUE = 3; - final static int ALPHA = 4; - final static int SATURATION = 5; - - Thread runner; - - DitherControls XControls; - DitherControls YControls; - DitherCanvas canvas; - - public DitherTest(GraphicsConfiguration gc) { - String xspec, yspec; - int xvals[] = new int[2]; - int yvals[] = new int[2]; - - xspec = "red"; - yspec = "blue"; - int xmethod = colormethod(xspec, xvals); - int ymethod = colormethod(yspec, yvals); - - setLayout(new BorderLayout()); - XControls = new DitherControls(this, xvals[0], xvals[1], - xmethod, false); - YControls = new DitherControls(this, yvals[0], yvals[1], - ymethod, true); - YControls.addRenderButton(); - add("North", XControls); - add("South", YControls); - add("Center", canvas = new DitherCanvas(gc)); - } + @Override + public void update(Graphics g) { + paint(g); + } - public void start() { - runner = new Thread(this); - runner.start(); - } + @Override + public Dimension getMinimumSize() { + return new Dimension(20, 20); + } - int colormethod(String s, int vals[]) { - int method = NOOP; + @Override + public Dimension getPreferredSize() { + return new Dimension(200, 200); + } - if (s == null) { - s = ""; + public Image getImage() { + return img; } - String lower = s.toLowerCase(); - int len = 0; - if (lower.startsWith("red")) { - method = RED; - lower = lower.substring(3); - } else if (lower.startsWith("green")) { - method = GREEN; - lower = lower.substring(5); - } else if (lower.startsWith("blue")) { - method = BLUE; - lower = lower.substring(4); - } else if (lower.startsWith("alpha")) { - method = ALPHA; - lower = lower.substring(4); - } else if (lower.startsWith("saturation")) { - method = SATURATION; - lower = lower.substring(10); + public void setImage(Image img) { + this.img = img; + paint(getGraphics()); } + } - if (method == NOOP) { - vals[0] = 0; - vals[1] = 0; - return method; + static class DitherTest extends Panel implements Runnable { + final static int NOOP = 0; + final static int RED = 1; + final static int GREEN = 2; + final static int BLUE = 3; + final static int ALPHA = 4; + final static int SATURATION = 5; + + Thread runner; + + DitherControls XControls; + DitherControls YControls; + DitherCanvas canvas; + + public DitherTest(GraphicsConfiguration gc) { + String xspec, yspec; + int xvals[] = new int[2]; + int yvals[] = new int[2]; + + xspec = "red"; + yspec = "blue"; + int xmethod = colormethod(xspec, xvals); + int ymethod = colormethod(yspec, yvals); + + setLayout(new BorderLayout()); + XControls = new DitherControls(this, xvals[0], xvals[1], + xmethod, false); + YControls = new DitherControls(this, yvals[0], yvals[1], + ymethod, true); + YControls.addRenderButton(); + add("North", XControls); + add("South", YControls); + add("Center", canvas = new DitherCanvas(gc)); } - int begval = 0; - int endval = 255; + public void start() { + runner = new Thread(this); + runner.start(); + } - try { - int dash = lower.indexOf('-'); - if (dash < 0) { - begval = endval = Integer.parseInt(lower); - } else { - begval = Integer.parseInt(lower.substring(0, dash)); - endval = Integer.parseInt(lower.substring(dash + 1)); + int colormethod(String s, int vals[]) { + int method = NOOP; + + if (s == null) { + s = ""; } - } catch (Exception e) { - } - if (begval < 0) { - begval = 0; - } - if (endval < 0) { - endval = 0; - } - if (begval > 255) { - begval = 255; - } - if (endval > 255) { - endval = 255; - } + String lower = s.toLowerCase(); + int len = 0; + if (lower.startsWith("red")) { + method = RED; + lower = lower.substring(3); + } else if (lower.startsWith("green")) { + method = GREEN; + lower = lower.substring(5); + } else if (lower.startsWith("blue")) { + method = BLUE; + lower = lower.substring(4); + } else if (lower.startsWith("alpha")) { + method = ALPHA; + lower = lower.substring(4); + } else if (lower.startsWith("saturation")) { + method = SATURATION; + lower = lower.substring(10); + } - vals[0] = begval; - vals[1] = endval; + if (method == NOOP) { + vals[0] = 0; + vals[1] = 0; + return method; + } - return method; - } + int begval = 0; + int endval = 255; - void applymethod(int c[], int method, int step, int total, int vals[]) { - if (method == NOOP) - return; - int val = ((total < 2) - ? vals[0] - : vals[0] + ((vals[1] - vals[0]) * step / (total - 1))); - switch (method) { - case RED: - c[0] = val; - break; - case GREEN: - c[1] = val; - break; - case BLUE: - c[2] = val; - break; - case ALPHA: - c[3] = val; - break; - case SATURATION: - int max = Math.max(Math.max(c[0], c[1]), c[2]); - int min = max * (255 - val) / 255; - if (c[0] == 0) { - c[0] = min; - } - if (c[1] == 0) { - c[1] = min; - } - if (c[2] == 0) { - c[2] = min; + try { + int dash = lower.indexOf('-'); + if (dash < 0) { + begval = endval = Integer.parseInt(lower); + } else { + begval = Integer.parseInt(lower.substring(0, dash)); + endval = Integer.parseInt(lower.substring(dash + 1)); } - break; + } catch (Exception e) { + } + + if (begval < 0) { + begval = 0; + } + if (endval < 0) { + endval = 0; + } + if (begval > 255) { + begval = 255; + } + if (endval > 255) { + endval = 255; + } + + vals[0] = begval; + vals[1] = endval; + + return method; } - } - public void run() { - canvas.setImage(null); // Wipe previous image - Image img = calculateImage(); - synchronized (this) { - if (img != null && runner == Thread.currentThread()) { - canvas.setImage(img); + void applymethod(int c[], int method, int step, int total, int vals[]) { + if (method == NOOP) + return; + int val = ((total < 2) + ? vals[0] + : vals[0] + ((vals[1] - vals[0]) * step / (total - 1))); + switch (method) { + case RED: + c[0] = val; + break; + case GREEN: + c[1] = val; + break; + case BLUE: + c[2] = val; + break; + case ALPHA: + c[3] = val; + break; + case SATURATION: + int max = Math.max(Math.max(c[0], c[1]), c[2]); + int min = max * (255 - val) / 255; + if (c[0] == 0) { + c[0] = min; + } + if (c[1] == 0) { + c[1] = min; + } + if (c[2] == 0) { + c[2] = min; + } + break; } } - } - /** - * Calculates and returns the image. Halts the calculation and returns - * null if stopped during the calculation. - */ - Image calculateImage() { - Thread me = Thread.currentThread(); - - int width = canvas.getSize().width; - int height = canvas.getSize().height; - int xvals[] = new int[2]; - int yvals[] = new int[2]; - int xmethod = XControls.getParams(xvals); - int ymethod = YControls.getParams(yvals); - int pixels[] = new int[width * height]; - int c[] = new int[4]; - int index = 0; - - for (int j = 0; j < height; j++) { - for (int i = 0; i < width; i++) { - c[0] = c[1] = c[2] = 0; - c[3] = 255; - if (xmethod < ymethod) { - applymethod(c, xmethod, i, width, xvals); - applymethod(c, ymethod, j, height, yvals); - } else { - applymethod(c, ymethod, j, height, yvals); - applymethod(c, xmethod, i, width, xvals); + @Override + public void run() { + canvas.setImage(null); // Wipe previous image + Image img = calculateImage(); + synchronized (this) { + if (img != null && runner == Thread.currentThread()) { + canvas.setImage(img); } - pixels[index++] = ((c[3] << 24) | - (c[0] << 16) | - (c[1] << 8) | - (c[2] << 0)); - - } - // Poll once per row to see if we've been told to stop. - if (runner != me) { - return null; } } - return createImage(new MemoryImageSource(width, height, - ColorModel.getRGBdefault(), pixels, 0, width)); - } + /** + * Calculates and returns the image. Halts the calculation and returns + * null if stopped during the calculation. + */ + Image calculateImage() { + Thread me = Thread.currentThread(); + + int width = canvas.getSize().width; + int height = canvas.getSize().height; + int xvals[] = new int[2]; + int yvals[] = new int[2]; + int xmethod = XControls.getParams(xvals); + int ymethod = YControls.getParams(yvals); + int pixels[] = new int[width * height]; + int c[] = new int[4]; + int index = 0; + + for (int j = 0; j < height; j++) { + for (int i = 0; i < width; i++) { + c[0] = c[1] = c[2] = 0; + c[3] = 255; + if (xmethod < ymethod) { + applymethod(c, xmethod, i, width, xvals); + applymethod(c, ymethod, j, height, yvals); + } else { + applymethod(c, ymethod, j, height, yvals); + applymethod(c, xmethod, i, width, xvals); + } + pixels[index++] = ((c[3] << 24) | + (c[0] << 16) | + (c[1] << 8) | + (c[2] << 0)); - public String getInfo() { - return "An interactive demonstration of dithering."; - } + } + // Poll once per row to see if we've been told to stop. + if (runner != me) { + return null; + } + } - public String[][] getParameterInfo() { - String[][] info = { - {"xaxis", "{RED, GREEN, BLUE, PINK, ORANGE, MAGENTA, CYAN, WHITE, YELLOW, GRAY, DARKGRAY}", - "The color of the Y axis. Default is RED."}, - {"yaxis", "{RED, GREEN, BLUE, PINK, ORANGE, MAGENTA, CYAN, WHITE, YELLOW, GRAY, DARKGRAY}", - "The color of the X axis. Default is BLUE."} - }; - return info; - } -} + return createImage(new MemoryImageSource(width, height, + ColorModel.getRGBdefault(), pixels, 0, width)); + } -class DitherControls extends Panel implements ActionListener { - TextField start; - TextField end; - Button button; - Choice choice; - DitherTest dt; - - static LayoutManager dcLayout = new FlowLayout(FlowLayout.CENTER, 10, 5); - - public DitherControls(DitherTest app, int s, int e, int type, - boolean vertical) { - dt = app; - setLayout(dcLayout); - add(new Label(vertical ? "Vertical" : "Horizontal")); - add(choice = new Choice()); - choice.addItem("Noop"); - choice.addItem("Red"); - choice.addItem("Green"); - choice.addItem("Blue"); - choice.addItem("Alpha"); - choice.addItem("Saturation"); - choice.select(type); - add(start = new TextField(Integer.toString(s), 4)); - add(end = new TextField(Integer.toString(e), 4)); - } + public String getInfo() { + return "An interactive demonstration of dithering."; + } - public void addRenderButton() { - add(button = new Button("New Image")); - button.addActionListener(this); + public String[][] getParameterInfo() { + String[][] info = { + {"xaxis", "{RED, GREEN, BLUE, PINK, ORANGE, MAGENTA, CYAN, WHITE, YELLOW, GRAY, DARKGRAY}", + "The color of the Y axis. Default is RED."}, + {"yaxis", "{RED, GREEN, BLUE, PINK, ORANGE, MAGENTA, CYAN, WHITE, YELLOW, GRAY, DARKGRAY}", + "The color of the X axis. Default is BLUE."} + }; + return info; + } } - public int getParams(int vals[]) { - vals[0] = Integer.parseInt(start.getText()); - vals[1] = Integer.parseInt(end.getText()); - return choice.getSelectedIndex(); - } + static class DitherControls extends Panel implements ActionListener { + TextField start; + TextField end; + Button button; + Choice choice; + DitherTest dt; + + static LayoutManager dcLayout = new FlowLayout(FlowLayout.CENTER, 10, 5); + + public DitherControls(DitherTest app, int s, int e, int type, + boolean vertical) { + dt = app; + setLayout(dcLayout); + add(new Label(vertical ? "Vertical" : "Horizontal")); + add(choice = new Choice()); + choice.addItem("Noop"); + choice.addItem("Red"); + choice.addItem("Green"); + choice.addItem("Blue"); + choice.addItem("Alpha"); + choice.addItem("Saturation"); + choice.select(type); + add(start = new TextField(Integer.toString(s), 4)); + add(end = new TextField(Integer.toString(e), 4)); + } - public void actionPerformed(ActionEvent e) { - if (e.getSource() == button) { - dt.start(); + public void addRenderButton() { + add(button = new Button("New Image")); + button.addActionListener(this); + } + + public int getParams(int vals[]) { + vals[0] = Integer.parseInt(start.getText()); + vals[1] = Integer.parseInt(end.getText()); + return choice.getSelectedIndex(); + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == button) { + dt.start(); + } } } } From bf7d40d0486b7b4e4820bb5d08a63c446ea3291d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Maillard?= Date: Wed, 11 Jun 2025 11:08:38 +0000 Subject: [PATCH 004/213] 8356751: IGV: clean up redundant field _should_send_method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Manuel Hässig Reviewed-by: mhaessig, thartmann, dfenacci --- src/hotspot/share/opto/idealGraphPrinter.cpp | 16 ++++++---------- src/hotspot/share/opto/idealGraphPrinter.hpp | 1 - 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/opto/idealGraphPrinter.cpp b/src/hotspot/share/opto/idealGraphPrinter.cpp index 3721394c112..1ecb46eaf5a 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.cpp +++ b/src/hotspot/share/opto/idealGraphPrinter.cpp @@ -155,7 +155,6 @@ void IdealGraphPrinter::init(const char* file_name, bool use_multiple_files, boo // in the mach where kill projections have no users but should // appear in the dump. _traverse_outs = true; - _should_send_method = true; _output = nullptr; buffer[0] = 0; _depth = 0; @@ -300,13 +299,11 @@ void IdealGraphPrinter::print_inline_tree(InlineTree *tree) { void IdealGraphPrinter::print_inlining() { // Print inline tree - if (_should_send_method) { - InlineTree *inlineTree = C->ilt(); - if (inlineTree != nullptr) { - print_inline_tree(inlineTree); - } else { - // print this method only - } + InlineTree *inlineTree = C->ilt(); + if (inlineTree != nullptr) { + print_inline_tree(inlineTree); + } else { + // print this method only } } @@ -382,7 +379,6 @@ void IdealGraphPrinter::begin_method() { tail(PROPERTIES_ELEMENT); - _should_send_method = true; this->_current_method = method; _xml->flush(); @@ -975,7 +971,7 @@ void IdealGraphPrinter::print_graph(const char* name, const frame* fr) { // Print current ideal graph void IdealGraphPrinter::print(const char* name, Node* node, GrowableArray& visible_nodes, const frame* fr) { - if (!_current_method || !_should_send_method || node == nullptr) return; + if (!_current_method || node == nullptr) return; if (name == nullptr) { stringStream graph_name; diff --git a/src/hotspot/share/opto/idealGraphPrinter.hpp b/src/hotspot/share/opto/idealGraphPrinter.hpp index 69ba2841506..7e68ce6c00f 100644 --- a/src/hotspot/share/opto/idealGraphPrinter.hpp +++ b/src/hotspot/share/opto/idealGraphPrinter.hpp @@ -110,7 +110,6 @@ class IdealGraphPrinter : public CHeapObj { ciMethod *_current_method; int _depth; char buffer[2048]; - bool _should_send_method; PhaseChaitin* _chaitin; bool _traverse_outs; Compile *C; From 42ab8fcfb98eacb2d93f59c012360a99a16e5450 Mon Sep 17 00:00:00 2001 From: Anton Artemov Date: Wed, 11 Jun 2025 12:42:57 +0000 Subject: [PATCH 005/213] 8265754: Move suspend/resume API from HandshakeState Reviewed-by: coleenp, dholmes, pchilanomate --- src/hotspot/share/runtime/handshake.cpp | 126 +------------- src/hotspot/share/runtime/handshake.hpp | 34 +--- src/hotspot/share/runtime/javaThread.cpp | 5 +- src/hotspot/share/runtime/javaThread.hpp | 7 +- .../share/runtime/suspendResumeManager.cpp | 158 ++++++++++++++++++ .../share/runtime/suspendResumeManager.hpp | 70 ++++++++ 6 files changed, 241 insertions(+), 159 deletions(-) create mode 100644 src/hotspot/share/runtime/suspendResumeManager.cpp create mode 100644 src/hotspot/share/runtime/suspendResumeManager.hpp diff --git a/src/hotspot/share/runtime/handshake.cpp b/src/hotspot/share/runtime/handshake.cpp index 6bed5e9d546..2c827b61602 100644 --- a/src/hotspot/share/runtime/handshake.cpp +++ b/src/hotspot/share/runtime/handshake.cpp @@ -465,9 +465,7 @@ HandshakeState::HandshakeState(JavaThread* target) : _queue(), _lock(Monitor::nosafepoint, "HandshakeState_lock"), _active_handshaker(), - _async_exceptions_blocked(false), - _suspended(false), - _async_suspend_handshake(false) { + _async_exceptions_blocked(false) { } HandshakeState::~HandshakeState() { @@ -699,128 +697,8 @@ HandshakeState::ProcessResult HandshakeState::try_process(HandshakeOperation* ma return op == match_op ? HandshakeState::_succeeded : HandshakeState::_processed; } -void HandshakeState::do_self_suspend() { - assert(Thread::current() == _handshakee, "should call from _handshakee"); - assert(_lock.owned_by_self(), "Lock must be held"); - assert(!_handshakee->has_last_Java_frame() || _handshakee->frame_anchor()->walkable(), "should have walkable stack"); - assert(_handshakee->thread_state() == _thread_blocked, "Caller should have transitioned to _thread_blocked"); - - while (is_suspended()) { - log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " suspended", p2i(_handshakee)); - _lock.wait_without_safepoint_check(); - } - log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " resumed", p2i(_handshakee)); -} - -// This is the closure that prevents a suspended JavaThread from -// escaping the suspend request. -class ThreadSelfSuspensionHandshake : public AsyncHandshakeClosure { - public: - ThreadSelfSuspensionHandshake() : AsyncHandshakeClosure("ThreadSelfSuspensionHandshake") {} - void do_thread(Thread* thr) { - JavaThread* current = JavaThread::cast(thr); - assert(current == Thread::current(), "Must be self executed."); - JavaThreadState jts = current->thread_state(); - - current->set_thread_state(_thread_blocked); - current->handshake_state()->do_self_suspend(); - current->set_thread_state(jts); - current->handshake_state()->set_async_suspend_handshake(false); - } - virtual bool is_suspend() { return true; } -}; - -bool HandshakeState::suspend_with_handshake(bool register_vthread_SR) { - assert(_handshakee->threadObj() != nullptr, "cannot suspend with a null threadObj"); - if (_handshakee->is_exiting()) { - log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " exiting", p2i(_handshakee)); - return false; - } - if (has_async_suspend_handshake()) { - if (is_suspended()) { - // Target is already suspended. - log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " already suspended", p2i(_handshakee)); - return false; - } else { - // Target is going to wake up and leave suspension. - // Let's just stop the thread from doing that. - log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " re-suspended", p2i(_handshakee)); - set_suspended(true, register_vthread_SR); - return true; - } - } - // no suspend request - assert(!is_suspended(), "cannot be suspended without a suspend request"); - // Thread is safe, so it must execute the request, thus we can count it as suspended - // from this point. - set_suspended(true, register_vthread_SR); - set_async_suspend_handshake(true); - log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " suspended, arming ThreadSuspension", p2i(_handshakee)); - ThreadSelfSuspensionHandshake* ts = new ThreadSelfSuspensionHandshake(); - Handshake::execute(ts, _handshakee); - return true; -} - -// This is the closure that synchronously honors the suspend request. -class SuspendThreadHandshake : public HandshakeClosure { - bool _register_vthread_SR; - bool _did_suspend; -public: - SuspendThreadHandshake(bool register_vthread_SR) : HandshakeClosure("SuspendThread"), - _register_vthread_SR(register_vthread_SR), _did_suspend(false) {} - void do_thread(Thread* thr) { - JavaThread* target = JavaThread::cast(thr); - _did_suspend = target->handshake_state()->suspend_with_handshake(_register_vthread_SR); - } - bool did_suspend() { return _did_suspend; } -}; - -bool HandshakeState::suspend(bool register_vthread_SR) { - JVMTI_ONLY(assert(!_handshakee->is_in_VTMS_transition(), "no suspend allowed in VTMS transition");) - JavaThread* self = JavaThread::current(); - if (_handshakee == self) { - // If target is the current thread we can bypass the handshake machinery - // and just suspend directly - ThreadBlockInVM tbivm(self); - MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag); - set_suspended(true, register_vthread_SR); - do_self_suspend(); - return true; - } else { - SuspendThreadHandshake st(register_vthread_SR); - Handshake::execute(&st, _handshakee); - return st.did_suspend(); - } -} - -bool HandshakeState::resume(bool register_vthread_SR) { - MutexLocker ml(&_lock, Mutex::_no_safepoint_check_flag); - if (!is_suspended()) { - assert(!_handshakee->is_suspended(), "cannot be suspended without a suspend request"); - return false; - } - // Resume the thread. - set_suspended(false, register_vthread_SR); - _lock.notify(); - return true; -} - -void HandshakeState::set_suspended(bool is_suspend, bool register_vthread_SR) { -#if INCLUDE_JVMTI - if (register_vthread_SR) { - assert(_handshakee->is_vthread_mounted(), "sanity check"); - if (is_suspend) { - JvmtiVTSuspender::register_vthread_suspend(_handshakee->vthread()); - } else { - JvmtiVTSuspender::register_vthread_resume(_handshakee->vthread()); - } - } -#endif - Atomic::store(&_suspended, is_suspend); -} - void HandshakeState::handle_unsafe_access_error() { - if (is_suspended()) { + if (_handshakee->is_suspended()) { // A suspend handshake was added to the queue after the // unsafe access error. Since the suspender has already // considered this JT as suspended and assumes it won't go diff --git a/src/hotspot/share/runtime/handshake.hpp b/src/hotspot/share/runtime/handshake.hpp index 9e963003053..ca9cef76f5d 100644 --- a/src/hotspot/share/runtime/handshake.hpp +++ b/src/hotspot/share/runtime/handshake.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,6 @@ class HandshakeOperation; class AsyncHandshakeOperation; class JavaThread; -class SuspendThreadHandshake; -class ThreadSelfSuspensionHandshake; class UnsafeAccessErrorHandshake; class ThreadsListHandle; @@ -88,8 +86,6 @@ class JvmtiRawMonitor; // operation is only done by either VMThread/Handshaker on behalf of the // JavaThread or by the target JavaThread itself. class HandshakeState { - friend ThreadSelfSuspensionHandshake; - friend SuspendThreadHandshake; friend UnsafeAccessErrorHandshake; friend JavaThread; // This a back reference to the JavaThread, @@ -98,7 +94,7 @@ class HandshakeState { // The queue containing handshake operations to be performed on _handshakee. FilterQueue _queue; // Provides mutual exclusion to this state and queue. Also used for - // JavaThread suspend/resume operations. + // JavaThread suspend/resume operations performed by SuspendResumeManager. Monitor _lock; // Set to the thread executing the handshake operation. Thread* volatile _active_handshaker; @@ -160,31 +156,5 @@ class HandshakeState { bool async_exceptions_blocked() { return _async_exceptions_blocked; } void set_async_exceptions_blocked(bool b) { _async_exceptions_blocked = b; } void handle_unsafe_access_error(); - - // Suspend/resume support - private: - // This flag is true when the thread owning this - // HandshakeState (the _handshakee) is suspended. - volatile bool _suspended; - // This flag is true while there is async handshake (trap) - // on queue. Since we do only need one, we can reuse it if - // thread gets suspended again (after a resume) - // and we have not yet processed it. - bool _async_suspend_handshake; - - // Called from the suspend handshake. - bool suspend_with_handshake(bool register_vthread_SR); - // Called from the async handshake (the trap) - // to stop a thread from continuing execution when suspended. - void do_self_suspend(); - - bool is_suspended() { return Atomic::load(&_suspended); } - void set_suspended(bool to, bool register_vthread_SR); - bool has_async_suspend_handshake() { return _async_suspend_handshake; } - void set_async_suspend_handshake(bool to) { _async_suspend_handshake = to; } - - bool suspend(bool register_vthread_SR); - bool resume(bool register_vthread_SR); }; - #endif // SHARE_RUNTIME_HANDSHAKE_HPP diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index f3ad0e0a325..37ecb1c6f9a 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -498,6 +498,7 @@ JavaThread::JavaThread(MemTag mem_tag) : _pending_interrupted_exception(false), _handshake(this), + _suspend_resume_manager(this, &_handshake._lock), _popframe_preserved_args(nullptr), _popframe_preserved_args_size(0), @@ -1200,13 +1201,13 @@ bool JavaThread::java_suspend(bool register_vthread_SR) { guarantee(Thread::is_JavaThread_protected(/* target */ this), "target JavaThread is not protected in calling context."); - return this->handshake_state()->suspend(register_vthread_SR); + return this->suspend_resume_manager()->suspend(register_vthread_SR); } bool JavaThread::java_resume(bool register_vthread_SR) { guarantee(Thread::is_JavaThread_protected_by_TLH(/* target */ this), "missing ThreadsListHandle in calling context."); - return this->handshake_state()->resume(register_vthread_SR); + return this->suspend_resume_manager()->resume(register_vthread_SR); } // Wait for another thread to perform object reallocation and relocking on behalf of diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 968dfd0ce48..af46492622d 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -40,6 +40,7 @@ #include "runtime/safepointMechanism.hpp" #include "runtime/stackWatermarkSet.hpp" #include "runtime/stackOverflow.hpp" +#include "runtime/suspendResumeManager.hpp" #include "runtime/thread.hpp" #include "runtime/threadHeapSampler.hpp" #include "runtime/threadIdentifier.hpp" @@ -694,9 +695,13 @@ class JavaThread: public Thread { // Suspend/resume support for JavaThread // higher-level suspension/resume logic called by the public APIs +private: + SuspendResumeManager _suspend_resume_manager; +public: bool java_suspend(bool register_vthread_SR); bool java_resume(bool register_vthread_SR); - bool is_suspended() { return _handshake.is_suspended(); } + bool is_suspended() { return _suspend_resume_manager.is_suspended(); } + SuspendResumeManager* suspend_resume_manager() { return &_suspend_resume_manager; } // Check for async exception in addition to safepoint. static void check_special_condition_for_native_trans(JavaThread *thread); diff --git a/src/hotspot/share/runtime/suspendResumeManager.cpp b/src/hotspot/share/runtime/suspendResumeManager.cpp new file mode 100644 index 00000000000..fd14f73f553 --- /dev/null +++ b/src/hotspot/share/runtime/suspendResumeManager.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "logging/log.hpp" +#include "logging/logStream.hpp" +#include "memory/resourceArea.hpp" +#include "prims/jvmtiThreadState.hpp" +#include "runtime/atomic.hpp" +#include "runtime/globals.hpp" +#include "runtime/handshake.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/javaThread.inline.hpp" +#include "runtime/suspendResumeManager.hpp" + +// This is the closure that prevents a suspended JavaThread from +// escaping the suspend request. +class ThreadSelfSuspensionHandshake : public AsyncHandshakeClosure { +public: + ThreadSelfSuspensionHandshake() : AsyncHandshakeClosure("ThreadSelfSuspensionHandshake") {} + void do_thread(Thread* thr) { + JavaThread* current = JavaThread::cast(thr); + assert(current == Thread::current(), "Must be self executed."); + JavaThreadState jts = current->thread_state(); + + current->set_thread_state(_thread_blocked); + current->suspend_resume_manager()->do_owner_suspend(); + current->set_thread_state(jts); + current->suspend_resume_manager()->set_async_suspend_handshake(false); + } + virtual bool is_suspend() { return true; } +}; + +// This is the closure that synchronously honors the suspend request. +class SuspendThreadHandshake : public HandshakeClosure { + bool _register_vthread_SR; + bool _did_suspend; +public: + SuspendThreadHandshake(bool register_vthread_SR) : HandshakeClosure("SuspendThread"), + _register_vthread_SR(register_vthread_SR), _did_suspend(false) { + } + void do_thread(Thread* thr) { + JavaThread* target = JavaThread::cast(thr); + _did_suspend = target->suspend_resume_manager()->suspend_with_handshake(_register_vthread_SR); + } + bool did_suspend() { return _did_suspend; } +}; + +void SuspendResumeManager::set_suspended(bool is_suspend, bool register_vthread_SR) { +#if INCLUDE_JVMTI + if (register_vthread_SR) { + assert(_target->is_vthread_mounted(), "sanity check"); + if (is_suspend) { + JvmtiVTSuspender::register_vthread_suspend(_target->vthread()); + } + else { + JvmtiVTSuspender::register_vthread_resume(_target->vthread()); + } + } +#endif + Atomic::store(&_suspended, is_suspend); +} + +bool SuspendResumeManager::suspend(bool register_vthread_SR) { + JVMTI_ONLY(assert(!_target->is_in_VTMS_transition(), "no suspend allowed in VTMS transition");) + JavaThread* self = JavaThread::current(); + if (_target == self) { + // If target is the current thread we can bypass the handshake machinery + // and just suspend directly + ThreadBlockInVM tbivm(self); + MutexLocker ml(_state_lock, Mutex::_no_safepoint_check_flag); + set_suspended(true, register_vthread_SR); + do_owner_suspend(); + return true; + } else { + SuspendThreadHandshake st(register_vthread_SR); + Handshake::execute(&st, _target); + return st.did_suspend(); + } +} + +bool SuspendResumeManager::resume(bool register_vthread_SR) { + MutexLocker ml(_state_lock, Mutex::_no_safepoint_check_flag); + if (!is_suspended()) { + assert(!_target->is_suspended(), "cannot be suspended without a suspend request"); + return false; + } + // Resume the thread. + set_suspended(false, register_vthread_SR); + _state_lock->notify(); + return true; +} + +void SuspendResumeManager::do_owner_suspend() { + assert(Thread::current() == _target, "should call from _target"); + assert(_state_lock->owned_by_self(), "Lock must be held"); + assert(!_target->has_last_Java_frame() || _target->frame_anchor()->walkable(), "should have walkable stack"); + assert(_target->thread_state() == _thread_blocked, "Caller should have transitioned to _thread_blocked"); + + while (is_suspended()) { + log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " suspended", p2i(_target)); + _state_lock->wait_without_safepoint_check(); + } + log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " resumed", p2i(_target)); +} + +bool SuspendResumeManager::suspend_with_handshake(bool register_vthread_SR) { + assert(_target->threadObj() != nullptr, "cannot suspend with a null threadObj"); + if (_target->is_exiting()) { + log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " exiting", p2i(_target)); + return false; + } + if (has_async_suspend_handshake()) { + if (is_suspended()) { + // Target is already suspended. + log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " already suspended", p2i(_target)); + return false; + } else { + // Target is going to wake up and leave suspension. + // Let's just stop the thread from doing that. + log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " re-suspended", p2i(_target)); + set_suspended(true, register_vthread_SR); + return true; + } + } + // no suspend request + assert(!is_suspended(), "cannot be suspended without a suspend request"); + // Thread is safe, so it must execute the request, thus we can count it as suspended + // from this point. + set_suspended(true, register_vthread_SR); + set_async_suspend_handshake(true); + log_trace(thread, suspend)("JavaThread:" INTPTR_FORMAT " suspended, arming ThreadSuspension", p2i(_target)); + ThreadSelfSuspensionHandshake* ts = new ThreadSelfSuspensionHandshake(); + Handshake::execute(ts, _target); + return true; +} + +SuspendResumeManager::SuspendResumeManager(JavaThread* thread, Monitor* state_lock) : _target(thread), _state_lock(state_lock), _suspended(false), _async_suspend_handshake(false) {} diff --git a/src/hotspot/share/runtime/suspendResumeManager.hpp b/src/hotspot/share/runtime/suspendResumeManager.hpp new file mode 100644 index 00000000000..fed3b34055e --- /dev/null +++ b/src/hotspot/share/runtime/suspendResumeManager.hpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_RUNTIME_SUSPENDRESUMEMANAGER_HPP +#define SHARE_RUNTIME_SUSPENDRESUMEMANAGER_HPP + +class SuspendThreadHandshake; +class ThreadSelfSuspensionHandshake; + +class SuspendResumeManager { + friend SuspendThreadHandshake; + friend ThreadSelfSuspensionHandshake; + friend JavaThread; + + JavaThread* _target; + Monitor* _state_lock; + + SuspendResumeManager(JavaThread* thread, Monitor* state_lock); + + // This flag is true when the thread owning this + // SuspendResumeManager (the _target) is suspended. + volatile bool _suspended; + // This flag is true while there is async handshake (trap) + // on queue. Since we do only need one, we can reuse it if + // thread gets suspended again (after a resume) + // and we have not yet processed it. + bool _async_suspend_handshake; + + bool suspend(bool register_vthread_SR); + bool resume(bool register_vthread_SR); + + // Called from the async handshake (the trap) + // to stop a thread from continuing execution when suspended. + void do_owner_suspend(); + + // Called from the suspend handshake. + bool suspend_with_handshake(bool register_vthread_SR); + + void set_suspended(bool to, bool register_vthread_SR); + + bool is_suspended() { + return Atomic::load(&_suspended); + } + + bool has_async_suspend_handshake() { return _async_suspend_handshake; } + void set_async_suspend_handshake(bool to) { _async_suspend_handshake = to; } +}; + +#endif // SHARE_RUNTIME_SUSPENDRESUMEMANAGER_HPP From 7d7fc69355e6f5421cf09f93290270bb16d13182 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 11 Jun 2025 13:32:57 +0000 Subject: [PATCH 006/213] 8357570: [macOS] os::Bsd::available_memory() might return too low values Reviewed-by: clanger, mdoerr, lucy --- src/hotspot/os/bsd/os_bsd.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 9f77d5a4bde..6f7d9a6de37 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -154,7 +154,8 @@ julong os::Bsd::available_memory() { assert(kerr == KERN_SUCCESS, "host_statistics64 failed - check mach_host_self() and count"); if (kerr == KERN_SUCCESS) { - available = vmstat.free_count * os::vm_page_size(); + // free_count is just a lowerbound, other page categories can be freed too and make memory available + available = (vmstat.free_count + vmstat.inactive_count + vmstat.purgeable_count) * os::vm_page_size(); } #endif return available; From c98dffa186d48c41e76fd3a60e0129a8da60310f Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Wed, 11 Jun 2025 13:48:56 +0000 Subject: [PATCH 007/213] 8357982: Fix several failing BMI tests with -XX:+UseAPX Reviewed-by: epeter, sviswanathan --- src/hotspot/cpu/x86/x86_64.ad | 14 ++++++++---- .../intrinsics/bmi/verifycode/AndnTestI.java | 15 ++++++++++++- .../intrinsics/bmi/verifycode/BlsiTestI.java | 17 ++++++++++++++ .../bmi/verifycode/BlsmskTestI.java | 19 +++++++++++++++- .../intrinsics/bmi/verifycode/BlsrTestI.java | 20 ++++++++++++++++- .../bmi/verifycode/BmiIntrinsicBase.java | 22 +++++++++++++++---- .../bmi/verifycode/BzhiTestI2L.java | 17 +++++++++++++- .../intrinsics/bmi/verifycode/LZcntTestI.java | 6 ++++- .../intrinsics/bmi/verifycode/TZcntTestI.java | 6 ++++- 9 files changed, 122 insertions(+), 14 deletions(-) diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index d17bdf5e2c9..7b545f0f5f7 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -10531,7 +10531,8 @@ instruct xorI_rReg_im1_ndd(rRegI dst, rRegI src, immI_M1 imm) // Xor Register with Immediate instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr) %{ - predicate(!UseAPX); + // Strict predicate check to make selection of xorI_rReg_im1 cost agnostic if immI src is -1. + predicate(!UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1); match(Set dst (XorI dst src)); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -10545,7 +10546,8 @@ instruct xorI_rReg_imm(rRegI dst, immI src, rFlagsReg cr) instruct xorI_rReg_rReg_imm_ndd(rRegI dst, rRegI src1, immI src2, rFlagsReg cr) %{ - predicate(UseAPX); + // Strict predicate check to make selection of xorI_rReg_im1_ndd cost agnostic if immI src2 is -1. + predicate(UseAPX && n->in(2)->bottom_type()->is_int()->get_con() != -1); match(Set dst (XorI src1 src2)); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -10563,6 +10565,7 @@ instruct xorI_rReg_mem_imm_ndd(rRegI dst, memory src1, immI src2, rFlagsReg cr) predicate(UseAPX); match(Set dst (XorI (LoadI src1) src2)); effect(KILL cr); + ins_cost(150); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); format %{ "exorl $dst, $src1, $src2\t# int ndd" %} @@ -11205,7 +11208,8 @@ instruct xorL_rReg_im1_ndd(rRegL dst,rRegL src, immL_M1 imm) // Xor Register with Immediate instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr) %{ - predicate(!UseAPX); + // Strict predicate check to make selection of xorL_rReg_im1 cost agnostic if immL32 src is -1. + predicate(!UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L); match(Set dst (XorL dst src)); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -11219,7 +11223,8 @@ instruct xorL_rReg_imm(rRegL dst, immL32 src, rFlagsReg cr) instruct xorL_rReg_rReg_imm(rRegL dst, rRegL src1, immL32 src2, rFlagsReg cr) %{ - predicate(UseAPX); + // Strict predicate check to make selection of xorL_rReg_im1_ndd cost agnostic if immL32 src2 is -1. + predicate(UseAPX && n->in(2)->bottom_type()->is_long()->get_con() != -1L); match(Set dst (XorL src1 src2)); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); @@ -11238,6 +11243,7 @@ instruct xorL_rReg_mem_imm(rRegL dst, memory src1, immL32 src2, rFlagsReg cr) match(Set dst (XorL (LoadL src1) src2)); effect(KILL cr); flag(PD::Flag_sets_sign_flag, PD::Flag_sets_zero_flag, PD::Flag_sets_parity_flag, PD::Flag_clears_overflow_flag, PD::Flag_clears_carry_flag); + ins_cost(150); format %{ "exorq $dst, $src1, $src2\t# long ndd" %} ins_encode %{ diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/AndnTestI.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/AndnTestI.java index 4ff18b0744c..4145b0f5641 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/AndnTestI.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/AndnTestI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,19 @@ protected AndnTestI(Method method) { (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes (byte) 0x00, (byte) 0xF2}; + // from intel apx specifications EVEX.128.NP.0F38.W0 F2 /r + instrMaskAPX = new byte[]{ + (byte) 0xFF, + (byte) 0x07, + (byte) 0x00, + (byte) 0x00, + (byte) 0xFF}; + instrPatternAPX = new byte[]{ + (byte) 0x62, // fixed prefix byte 0x62 for extended EVEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0x00, + (byte) 0xF2}; } public static void main(String[] args) throws Exception { diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsiTestI.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsiTestI.java index 17a11146f4e..346169f1aad 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsiTestI.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsiTestI.java @@ -59,6 +59,23 @@ protected BlsiTestI(Method method) { (byte) 0x00, (byte) 0xF3, (byte) 0b0001_1000}; // bits 543 == 011 (3) + + // from intel apx specifications EVEX.128.NP.0F38.W0 F3 /3(opcode extension) + instrMaskAPX = new byte[]{ + (byte) 0xFF, + (byte) 0x07, + (byte) 0x00, + (byte) 0x00, + (byte) 0xFF, + (byte) 0x38}; + + instrPatternAPX = new byte[]{ + (byte) 0x62, // fixed prefix byte 0x62 for extended EVEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0x00, + (byte) 0xF3, + (byte) 0b0001_1000}; // bits 543 == 011 (3) } public static void main(String[] args) throws Exception { diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java index 1fc0e99fe08..55d0368b84b 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsmskTestI.java @@ -57,7 +57,24 @@ protected BlsmskTestI(Method method) { (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes (byte) 0x00, (byte) 0xF3, - (byte) 0b0001_0000}; // bits 543 == 011 (3) + (byte) 0b0001_0000}; // bits 543 == 010 (2) + + // from intel apx specifications EVEX.128.NP.0F38.W1 F3 /2(opcode extension part of ModRM.REG) + instrMaskAPX = new byte[]{ + (byte) 0xFF, + (byte) 0x07, + (byte) 0x00, + (byte) 0x00, + (byte) 0xFF, + (byte) 0x38}; + + instrPatternAPX = new byte[]{ + (byte) 0x62, // fixed prefix byte 0x62 for extended EVEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0x00, + (byte) 0xF3, + (byte) 0b0001_0000}; // bits 543 == 010 (2) } public static void main(String[] args) throws Exception { diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsrTestI.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsrTestI.java index 57523f11086..3841a2f155c 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsrTestI.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BlsrTestI.java @@ -58,7 +58,25 @@ protected BlsrTestI(Method method) { (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes (byte) 0x00, (byte) 0xF3, - (byte) 0b0000_1000}; // bits 543 == 011 (3) + (byte) 0b0000_1000}; // bits 543 == 001 (1) + + // from intel apx specifications EVEX.128.NP.0F38.W1 F3 /1(opcode extension part of ModRM.REG) + instrMaskAPX = new byte[]{ + (byte) 0xFF, + (byte) 0x07, + (byte) 0x00, + (byte) 0x00, + (byte) 0xFF, + (byte) 0x38}; + + instrPatternAPX = new byte[]{ + (byte) 0x62, // fixed prefix byte 0x62 for extended EVEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0x00, + (byte) 0xF3, + (byte) 0b0000_1000}; // bits 543 == 001 (1) + } public static void main(String[] args) throws Exception { diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java index 743e371d5c2..0e8c8fe9514 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BmiIntrinsicBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -111,7 +111,8 @@ protected void checkCompilation(Executable executable, int level) { protected void checkEmittedCode(Executable executable) { final byte[] nativeCode = NMethod.get(executable, false).insts; final byte[] matchInstrPattern = (((BmiTestCase) testCase).getTestCaseX64() && Platform.isX64()) ? ((BmiTestCase_x64) testCase).getInstrPattern_x64() : ((BmiTestCase) testCase).getInstrPattern(); - if (!((BmiTestCase) testCase).verifyPositive(nativeCode)) { + boolean use_apx = CPUInfo.hasFeature("apx_f"); + if (!((BmiTestCase) testCase).verifyPositive(nativeCode, use_apx)) { throw new AssertionError(testCase.name() + " " + "CPU instructions expected not found in nativeCode: " + Utils.toHexString(nativeCode) + " ---- Expected instrPattern: " + Utils.toHexString(matchInstrPattern)); } else { @@ -124,6 +125,8 @@ abstract static class BmiTestCase implements CompilerWhiteBoxTest.TestCase { private final Method method; protected byte[] instrMask; protected byte[] instrPattern; + protected byte[] instrMaskAPX; + protected byte[] instrPatternAPX; protected boolean isLongOperation; protected String cpuFlag = "bmi1"; protected String vmFlag = "UseBMI1Instructions"; @@ -160,6 +163,13 @@ protected int countCpuInstructions(byte[] nativeCode) { return countCpuInstructions(nativeCode, instrMask, instrPattern); } + protected int countCpuInstructionsAPX(byte[] nativeCode) { + if (instrMaskAPX == null || instrPatternAPX == null) { + return 0; + } + return countCpuInstructions(nativeCode, instrMaskAPX, instrPatternAPX); + } + public static int countCpuInstructions(byte[] nativeCode, byte[] instrMask, byte[] instrPattern) { int count = 0; int patternSize = Math.min(instrMask.length, instrPattern.length); @@ -181,8 +191,12 @@ public static int countCpuInstructions(byte[] nativeCode, byte[] instrMask, byte return count; } - public boolean verifyPositive(byte[] nativeCode) { - final int cnt = countCpuInstructions(nativeCode); + public boolean verifyPositive(byte[] nativeCode, boolean use_apx) { + int cnt = countCpuInstructions(nativeCode); + if (use_apx) { + System.out.println("CHECKING APX INST PATTERNS"); + cnt += countCpuInstructionsAPX(nativeCode); + } if (Platform.isX86()) { return cnt >= (isLongOperation ? 2 : 1); } else { diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java index daba485be50..4cf94a0eb8b 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/BzhiTestI2L.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,6 +73,21 @@ protected BzhiTestI2L(Method method) { (byte) 0x62, // 00010 implied 0F 38 leading opcode bytes (byte) 0xA8, (byte) 0xF5}; + + // from intel apx specifications EVEX.128.NP.0F38.W0 F5 /r + instrMaskAPX = new byte[]{ + (byte) 0xFF, + (byte) 0x07, + (byte) 0x00, + (byte) 0x00, + (byte) 0xFF}; + + instrPatternAPX = new byte[]{ + (byte) 0x62, // fixed prefix byte 0x62 for extended EVEX instruction + (byte) 0x02, // 00010 implied 0F 38 leading opcode bytes + (byte) 0x00, + (byte) 0x00, + (byte) 0xF5}; } public static void main(String[] args) throws Exception { diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/LZcntTestI.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/LZcntTestI.java index d1b88ffd9d0..c905fca34a2 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/LZcntTestI.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/LZcntTestI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,6 +51,10 @@ protected LZcntTestI(Method method) { instrMask_x64 = new byte[]{(byte) 0xFF, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}; instrPattern_x64 = new byte[]{(byte) 0xF3, (byte) 0x00, (byte) 0x0F, (byte) 0xBD}; + + // REX2 variant + instrMaskAPX = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte)0x80, (byte) 0xFF}; + instrPatternAPX = new byte[]{(byte) 0xF3, (byte) 0xD5, (byte) 0x80, (byte) 0xBD}; } public static void main(String[] args) throws Exception { diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/TZcntTestI.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/TZcntTestI.java index 641fdb0b203..8a8ce4508fa 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/TZcntTestI.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/verifycode/TZcntTestI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,10 @@ protected TZcntTestI(Method method) { instrMask_x64 = new byte[]{(byte) 0xFF, (byte) 0x00, (byte) 0xFF, (byte) 0xFF}; instrPattern_x64 = new byte[]{(byte) 0xF3, (byte) 0x00, (byte) 0x0F, (byte) 0xBC}; + + // REX2 variant + instrMaskAPX = new byte[]{(byte) 0xFF, (byte) 0xFF, (byte)0x80, (byte) 0xFF}; + instrPatternAPX = new byte[]{(byte) 0xF3, (byte) 0xD5, (byte) 0x80, (byte) 0xBC}; } public static void main(String[] args) throws Exception { From e5196fc24d2ec9e581af7803ac47036111fee029 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 11 Jun 2025 14:09:45 +0000 Subject: [PATCH 008/213] 8358764: (sc) SocketChannel.close when thread blocked in read causes connection to be reset (win) Reviewed-by: jpai, vyazici --- .../share/classes/sun/nio/ch/Net.java | 11 + .../classes/sun/nio/ch/SocketChannelImpl.java | 42 ++-- src/java.base/unix/native/libnio/ch/Net.c | 5 + src/java.base/windows/native/libnio/ch/Net.c | 7 +- .../PeerReadsAfterAsyncClose.java | 195 ++++++++++++++++++ 5 files changed, 243 insertions(+), 17 deletions(-) create mode 100644 test/jdk/java/nio/channels/SocketChannel/PeerReadsAfterAsyncClose.java diff --git a/src/java.base/share/classes/sun/nio/ch/Net.java b/src/java.base/share/classes/sun/nio/ch/Net.java index 5cd14a8b301..9ec7975a35c 100644 --- a/src/java.base/share/classes/sun/nio/ch/Net.java +++ b/src/java.base/share/classes/sun/nio/ch/Net.java @@ -94,6 +94,15 @@ static boolean useExclusiveBind() { return EXCLUSIVE_BIND; } + private static final StableValue SHUTDOWN_WRITE_BEFORE_CLOSE = StableValue.of(); + + /** + * Tells whether a TCP connection should be shutdown for writing before closing. + */ + static boolean shouldShutdownWriteBeforeClose() { + return SHUTDOWN_WRITE_BEFORE_CLOSE.orElseSet(Net::shouldShutdownWriteBeforeClose0); + } + /** * Tells whether both IPV6_XXX and IP_XXX socket options should be set on * IPv6 sockets. On some kernels, both IPV6_XXX and IP_XXX socket options @@ -462,6 +471,8 @@ private static boolean isFastTcpLoopbackRequested() { */ private static native int isExclusiveBindAvailable(); + private static native boolean shouldShutdownWriteBeforeClose0(); + private static native boolean shouldSetBothIPv4AndIPv6Options0(); private static native boolean canIPv6SocketJoinIPv4Group0(); diff --git a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index c1241a51f85..37e6a71d80d 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -846,7 +846,7 @@ public boolean isConnectionPending() { /** * Marks the beginning of a connect operation that might block. * @param blocking true if configured blocking - * @param isa the remote address + * @param sa the remote socket address * @throws ClosedChannelException if the channel is closed * @throws AlreadyConnectedException if already connected * @throws ConnectionPendingException is a connection is pending @@ -1070,8 +1070,8 @@ public boolean finishConnect() throws IOException { } /** - * Closes the socket if there are no I/O operations in progress and the - * channel is not registered with a Selector. + * Closes the socket if there are no I/O operations in progress (or no I/O + * operations tracked), and the channel is not registered with a Selector. */ private boolean tryClose() throws IOException { assert Thread.holdsLock(stateLock) && state == ST_CLOSING; @@ -1096,11 +1096,21 @@ private void tryFinishClose() { } /** - * Closes this channel when configured in blocking mode. + * Closes this channel when configured in blocking mode. If there are no I/O + * operations in progress (or tracked), then the channel's socket is closed. If + * there are I/O operations in progress then the behavior is platform specific. * - * If there is an I/O operation in progress then the socket is pre-closed - * and the I/O threads signalled, in which case the final close is deferred - * until all I/O operations complete. + * On Unix systems, the channel's socket is pre-closed. This unparks any virtual + * threads that are blocked in I/O operations on this channel. If there are + * platform threads blocked on the channel's socket then the socket is dup'ed + * and the platform threads signalled. The final close is deferred until all I/O + * operations complete. + * + * On Windows, the channel's socket is pre-closed. This unparks any virtual + * threads that are blocked in I/O operations on this channel. If there are no + * virtual threads blocked in I/O operations on this channel then the channel's + * socket is closed. If there are virtual threads in I/O then the final close is + * deferred until all I/O operations on virtual threads complete. * * Note that a channel configured blocking may be registered with a Selector * This arises when a key is canceled and the channel configured to blocking @@ -1112,17 +1122,17 @@ private void implCloseBlockingMode() throws IOException { boolean connected = (state == ST_CONNECTED); state = ST_CLOSING; - if (!tryClose()) { + if (connected && Net.shouldShutdownWriteBeforeClose()) { // shutdown output when linger interval not set to 0 - if (connected) { - try { - var SO_LINGER = StandardSocketOptions.SO_LINGER; - if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) { - Net.shutdown(fd, Net.SHUT_WR); - } - } catch (IOException ignore) { } - } + try { + var SO_LINGER = StandardSocketOptions.SO_LINGER; + if ((int) Net.getSocketOption(fd, SO_LINGER) != 0) { + Net.shutdown(fd, Net.SHUT_WR); + } + } catch (IOException ignore) { } + } + if (!tryClose()) { // prepare file descriptor for closing nd.preClose(fd, readerThread, writerThread); } diff --git a/src/java.base/unix/native/libnio/ch/Net.c b/src/java.base/unix/native/libnio/ch/Net.c index 98445c93731..28c1814f422 100644 --- a/src/java.base/unix/native/libnio/ch/Net.c +++ b/src/java.base/unix/native/libnio/ch/Net.c @@ -205,6 +205,11 @@ Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) { return -1; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_shouldShutdownWriteBeforeClose0(JNIEnv *env, jclass clazz) { + return JNI_FALSE; +} + JNIEXPORT jboolean JNICALL Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl) { diff --git a/src/java.base/windows/native/libnio/ch/Net.c b/src/java.base/windows/native/libnio/ch/Net.c index 3ccdbcc4752..105cb9cf743 100644 --- a/src/java.base/windows/native/libnio/ch/Net.c +++ b/src/java.base/windows/native/libnio/ch/Net.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,6 +117,11 @@ Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) { return 1; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_shouldShutdownWriteBeforeClose0(JNIEnv *env, jclass clazz) { + return JNI_TRUE; +} + JNIEXPORT jboolean JNICALL Java_sun_nio_ch_Net_shouldSetBothIPv4AndIPv6Options0(JNIEnv* env, jclass cl) { diff --git a/test/jdk/java/nio/channels/SocketChannel/PeerReadsAfterAsyncClose.java b/test/jdk/java/nio/channels/SocketChannel/PeerReadsAfterAsyncClose.java new file mode 100644 index 00000000000..2b6a6edf1d4 --- /dev/null +++ b/test/jdk/java/nio/channels/SocketChannel/PeerReadsAfterAsyncClose.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8358764 + * @summary Test closing a socket while a thread is blocked in read. The connection + * should be closed gracefuly so that the peer reads EOF. + * @run junit PeerReadsAfterAsyncClose + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.SocketChannel; +import java.util.Arrays; +import java.util.Objects; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import static org.junit.jupiter.api.Assertions.*; + +class PeerReadsAfterAsyncClose { + + static Stream factories() { + return Stream.of(Thread.ofPlatform().factory(), Thread.ofVirtual().factory()); + } + + /** + * Close SocketChannel while a thread is blocked reading from the channel's socket. + */ + @ParameterizedTest + @MethodSource("factories") + void testCloseDuringSocketChannelRead(ThreadFactory factory) throws Exception { + var loopback = InetAddress.getLoopbackAddress(); + try (var listener = new ServerSocket()) { + listener.bind(new InetSocketAddress(loopback, 0)); + + try (SocketChannel sc = SocketChannel.open(listener.getLocalSocketAddress()); + Socket peer = listener.accept()) { + + // start thread to read from channel + var cceThrown = new AtomicBoolean(); + Thread thread = factory.newThread(() -> { + try { + sc.read(ByteBuffer.allocate(1)); + fail(); + } catch (ClosedChannelException e) { + cceThrown.set(true); + } catch (Throwable e) { + e.printStackTrace(); + } + }); + thread.start(); + try { + // close SocketChannel when thread sampled in implRead + onReach(thread, "sun.nio.ch.SocketChannelImpl.implRead", () -> { + try { + sc.close(); + } catch (IOException ignore) { } + }); + + // peer should read EOF + int n = peer.getInputStream().read(); + assertEquals(-1, n); + } finally { + thread.join(); + } + assertEquals(true, cceThrown.get(), "ClosedChannelException not thrown"); + } + } + } + + /** + * Close Socket while a thread is blocked reading from the socket. + */ + @ParameterizedTest + @MethodSource("factories") + void testCloseDuringSocketUntimedRead(ThreadFactory factory) throws Exception { + testCloseDuringSocketRead(factory, 0); + } + + /** + * Close Socket while a thread is blocked reading from the socket with a timeout. + */ + @ParameterizedTest + @MethodSource("factories") + void testCloseDuringSockeTimedRead(ThreadFactory factory) throws Exception { + testCloseDuringSocketRead(factory, 60_000); + } + + private void testCloseDuringSocketRead(ThreadFactory factory, int timeout) throws Exception { + var loopback = InetAddress.getLoopbackAddress(); + try (var listener = new ServerSocket()) { + listener.bind(new InetSocketAddress(loopback, 0)); + + try (Socket s = new Socket(loopback, listener.getLocalPort()); + Socket peer = listener.accept()) { + + // start thread to read from socket + var seThrown = new AtomicBoolean(); + Thread thread = factory.newThread(() -> { + try { + s.setSoTimeout(timeout); + s.getInputStream().read(); + fail(); + } catch (SocketException e) { + seThrown.set(true); + } catch (Throwable e) { + e.printStackTrace(); + } + }); + thread.start(); + try { + // close Socket when thread sampled in implRead + onReach(thread, "sun.nio.ch.NioSocketImpl.implRead", () -> { + try { + s.close(); + } catch (IOException ignore) { } + }); + + // peer should read EOF + int n = peer.getInputStream().read(); + assertEquals(-1, n); + } finally { + thread.join(); + } + assertEquals(true, seThrown.get(), "SocketException not thrown"); + } + } + } + + /** + * Runs the given action when the given target thread is sampled at the given + * location. The location takes the form "{@code c.m}" where + * {@code c} is the fully qualified class name and {@code m} is the method name. + */ + private void onReach(Thread target, String location, Runnable action) { + int index = location.lastIndexOf('.'); + String className = location.substring(0, index); + String methodName = location.substring(index + 1); + Thread.ofPlatform().daemon(true).start(() -> { + try { + boolean found = false; + while (!found) { + found = contains(target.getStackTrace(), className, methodName); + if (!found) { + Thread.sleep(20); + } + } + action.run(); + } catch (Exception e) { + e.printStackTrace(); + } + }); + } + + /** + * Returns true if the given stack trace contains an element for the given class + * and method name. + */ + private boolean contains(StackTraceElement[] stack, String className, String methodName) { + return Arrays.stream(stack) + .anyMatch(e -> className.equals(e.getClassName()) + && methodName.equals(e.getMethodName())); + } +} \ No newline at end of file From e9216efefc12b04c372a0a7f47167c984be544b7 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 11 Jun 2025 16:04:26 +0000 Subject: [PATCH 009/213] 8358734: Remove JavaTimeSupplementary resource bundles Reviewed-by: jlu, joehw, iris --- src/java.base/share/classes/module-info.java | 3 +- .../sun/text/resources/FormatData.java | 349 +++++++++++++---- .../text/resources/JavaTimeSupplementary.java | 353 ------------------ .../JavaTimeSupplementaryProvider.java | 35 -- .../util/locale/provider/LocaleResources.java | 9 +- .../sun/util/resources/LocaleData.java | 101 +---- .../resources/ParallelListResourceBundle.java | 259 ------------- .../share/classes/module-info.java | 4 +- .../sun/text/resources/ext/FormatData.java | 6 +- .../sun/text/resources/ext/FormatData_ja.java | 8 +- .../provider/LocaleDataProvider.java | 4 +- 11 files changed, 301 insertions(+), 830 deletions(-) delete mode 100644 src/java.base/share/classes/sun/text/resources/JavaTimeSupplementary.java delete mode 100644 src/java.base/share/classes/sun/text/resources/JavaTimeSupplementaryProvider.java delete mode 100644 src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 07de3f2c57f..fe043dadab5 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -402,8 +402,7 @@ uses sun.text.spi.JavaTimeDateTimePatternProvider; uses sun.util.spi.CalendarProvider; uses sun.util.locale.provider.LocaleDataMetaInfo; - uses sun.util.resources.LocaleData.CommonResourceBundleProvider; - uses sun.util.resources.LocaleData.SupplementaryResourceBundleProvider; + uses sun.util.resources.LocaleData.LocaleDataResourceBundleProvider; // Built-in service providers that are located via ServiceLoader diff --git a/src/java.base/share/classes/sun/text/resources/FormatData.java b/src/java.base/share/classes/sun/text/resources/FormatData.java index f90317ee69f..541cb63fff9 100644 --- a/src/java.base/share/classes/sun/text/resources/FormatData.java +++ b/src/java.base/share/classes/sun/text/resources/FormatData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,6 @@ * questions. */ -/* - */ - /* * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved * (C) Copyright IBM Corp. 1996 - 1999 - All Rights Reserved @@ -79,11 +76,11 @@ package sun.text.resources; -import sun.util.resources.ParallelListResourceBundle; +import sun.util.resources.OpenListResourceBundle; -public class FormatData extends ParallelListResourceBundle { +public class FormatData extends OpenListResourceBundle { /** - * Overrides ListResourceBundle + * Overrides OpenListResourceBundle */ @Override protected final Object[][] getContents() { @@ -119,6 +116,109 @@ protected final Object[][] getContents() { "Reiwa", }; + // Moved from JavaTimeSupplementary + final String[] sharedQuarterNames = { + "Q1", + "Q2", + "Q3", + "Q4", + }; + + final String[] sharedQuarterNarrows = { + "1", + "2", + "3", + "4", + }; + + final String[] sharedDatePatterns = { + "GGGG y MMMM d, EEEE", + "GGGG y MMMM d", + "GGGG y MMM d", + "G y-MM-dd", + }; + + final String[] sharedDayAbbrs = { + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", + }; + + final String[] sharedDayNarrows = { + "S", + "M", + "T", + "W", + "T", + "F", + "S", + }; + + final String[] sharedEras = { + "", + "AH", + }; + + final String[] sharedMonthNarrows = { + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "", + }; + + final String[] sharedTimePatterns = { + "HH:mm:ss zzzz", + "HH:mm:ss z", + "HH:mm:ss", + "HH:mm", + }; + + final String[] sharedAmPmMarkers = { + "AM", + "PM", + }; + + final String[] sharedJavaTimeDatePatterns = { + "G y MMMM d, EEEE", + "G y MMMM d", + "G y MMM d", + "GGGGG y-MM-dd", + }; + + final String[] sharedShortEras = { + "Before R.O.C.", + "R.O.C.", + }; + + final String[] sharedMonthAbbrs = { + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", + "", + }; + return new Object[][] { { "MonthNames", new String[] { @@ -138,39 +238,9 @@ protected final Object[][] getContents() { } }, { "MonthAbbreviations", - new String[] { - "Jan", // abb january - "Feb", // abb february - "Mar", // abb march - "Apr", // abb april - "May", // abb may - "Jun", // abb june - "Jul", // abb july - "Aug", // abb august - "Sep", // abb september - "Oct", // abb october - "Nov", // abb november - "Dec", // abb december - "" // abb month 13 if applicable - } - }, + sharedMonthAbbrs }, { "MonthNarrows", - new String[] { - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "", - } - }, + sharedMonthNarrows }, { "DayNames", new String[] { "Sunday", // Sunday @@ -183,33 +253,11 @@ protected final Object[][] getContents() { } }, { "DayAbbreviations", - new String[] { - "Sun", // abb Sunday - "Mon", // abb Monday - "Tue", // abb Tuesday - "Wed", // abb Wednesday - "Thu", // abb Thursday - "Fri", // abb Friday - "Sat" // abb Saturday - } - }, + sharedDayAbbrs }, { "DayNarrows", - new String[] { - "S", - "M", - "T", - "W", - "T", - "F", - "S", - } - }, + sharedDayNarrows }, { "AmPmMarkers", - new String[] { - "AM", // am marker - "PM" // pm marker - } - }, + sharedAmPmMarkers }, { "narrow.AmPmMarkers", new String[] { "a", // am marker @@ -227,22 +275,17 @@ protected final Object[][] getContents() { } }, { "buddhist.Eras", - buddhistEras - }, + buddhistEras }, { "buddhist.short.Eras", - buddhistEras - }, + buddhistEras }, { "buddhist.narrow.Eras", - buddhistEras - }, + buddhistEras }, { "japanese.Eras", japaneseEras }, { "japanese.short.Eras", - japaneseEraAbbrs - }, + japaneseEraAbbrs }, { "japanese.narrow.Eras", - japaneseEraAbbrs - }, + japaneseEraAbbrs }, { "japanese.FirstYear", new String[] { // Japanese imperial calendar year name // empty in English @@ -898,6 +941,164 @@ protected final Object[][] getContents() { } }, { "DateTimePatternChars", "GyMdkHmsSEDFwWahKzZ" }, + + // Moved from JavaTimeSupplementary + { "QuarterAbbreviations", + sharedQuarterNames }, + { "QuarterNames", + sharedQuarterNames }, + { "QuarterNarrows", + sharedQuarterNarrows }, + { "field.dayperiod", + "Dayperiod" }, + { "field.era", + "Era" }, + { "field.hour", + "Hour" }, + { "field.minute", + "Minute" }, + { "field.month", + "Month" }, + { "field.second", + "Second" }, + { "field.week", + "Week" }, + { "field.weekday", + "Day of the Week" }, + { "field.year", + "Year" }, + { "field.zone", + "Zone" }, + { "islamic.DatePatterns", + sharedDatePatterns }, + { "islamic.DayAbbreviations", + sharedDayAbbrs }, + { "islamic.DayNames", + sharedDayAbbrs }, + { "islamic.DayNarrows", + sharedDayNarrows }, + { "islamic.Eras", + sharedEras }, + { "islamic.MonthAbbreviations", + new String[] { + "Muh.", + "Saf.", + "Rab. I", + "Rab. II", + "Jum. I", + "Jum. II", + "Raj.", + "Sha.", + "Ram.", + "Shaw.", + "Dhuʻl-Q.", + "Dhuʻl-H.", + "", + } + }, + { "islamic.MonthNames", + new String[] { + "Muharram", + "Safar", + "Rabiʻ I", + "Rabiʻ II", + "Jumada I", + "Jumada II", + "Rajab", + "Shaʻban", + "Ramadan", + "Shawwal", + "Dhuʻl-Qiʻdah", + "Dhuʻl-Hijjah", + "", + } + }, + { "islamic.MonthNarrows", + sharedMonthNarrows }, + { "islamic.QuarterNames", + sharedQuarterNames }, + { "islamic.QuarterNarrows", + sharedQuarterNarrows }, + { "islamic.TimePatterns", + sharedTimePatterns }, + { "islamic.abbreviated.AmPmMarkers", + sharedAmPmMarkers }, + { "islamic.long.Eras", + sharedEras }, + { "islamic.narrow.Eras", + sharedEras }, + { "islamic.short.Eras", + sharedEras }, + { "java.time.buddhist.DatePatterns", + sharedJavaTimeDatePatterns }, + { "java.time.buddhist.long.Eras", + new String[] { + "BC", + "BE", + } + }, + { "java.time.buddhist.short.Eras", + buddhistEras }, + { "java.time.islamic.DatePatterns", + sharedJavaTimeDatePatterns }, + { "java.time.japanese.DatePatterns", + new String[] { + "G y MMMM d (EEEE)", + "G y MMMM d", + "G y MMM d", + "GGGGGy.MM.dd", + } + }, + { "java.time.japanese.long.Eras", + japaneseEras }, + { "java.time.japanese.short.Eras", + japaneseEras }, + { "java.time.long.Eras", + new String[] { + "BCE", + "CE", + } + }, + { "java.time.roc.DatePatterns", + sharedJavaTimeDatePatterns }, + { "java.time.short.Eras", + julianEras }, + { "roc.AmPmMarkers", + sharedAmPmMarkers }, + { "roc.DatePatterns", + sharedDatePatterns }, + { "roc.DayNames", + sharedDayAbbrs }, + { "roc.DayNarrows", + sharedDayNarrows }, + { "roc.Eras", + sharedShortEras }, + { "roc.MonthAbbreviations", + sharedMonthAbbrs }, + { "roc.MonthNames", + sharedMonthAbbrs }, + { "roc.MonthNarrows", + sharedMonthNarrows }, + { "roc.QuarterNames", + sharedQuarterNames }, + { "roc.QuarterNarrows", + sharedQuarterNarrows }, + { "roc.TimePatterns", + sharedTimePatterns }, + { "roc.abbreviated.AmPmMarkers", + sharedAmPmMarkers }, + { "roc.long.Eras", + sharedShortEras }, + { "roc.narrow.AmPmMarkers", + sharedAmPmMarkers }, + { "roc.narrow.Eras", + sharedShortEras }, + { "roc.short.Eras", + sharedShortEras }, + { "timezone.gmtFormat", + "GMT{0}" }, + { "timezone.hourFormat", + "+HH:mm;-HH:mm" }, }; } } diff --git a/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementary.java b/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementary.java deleted file mode 100644 index cbcb724d258..00000000000 --- a/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementary.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. - * 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. - */ - -/* - * COPYRIGHT AND PERMISSION NOTICE - * - * Copyright (C) 1991-2016 Unicode, Inc. All rights reserved. - * Distributed under the Terms of Use in - * http://www.unicode.org/copyright.html. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of the Unicode data files and any associated documentation - * (the "Data Files") or Unicode software and any associated documentation - * (the "Software") to deal in the Data Files or Software - * without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, and/or sell copies of - * the Data Files or Software, and to permit persons to whom the Data Files - * or Software are furnished to do so, provided that - * (a) this copyright and permission notice appear with all copies - * of the Data Files or Software, - * (b) this copyright and permission notice appear in associated - * documentation, and - * (c) there is clear notice in each modified Data File or in the Software - * as well as in the documentation associated with the Data File(s) or - * Software that the data or software has been modified. - * - * THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF - * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE - * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT OF THIRD PARTY RIGHTS. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS - * NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL - * DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, - * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THE DATA FILES OR SOFTWARE. - * - * Except as contained in this notice, the name of a copyright holder - * shall not be used in advertising or otherwise to promote the sale, - * use or other dealings in these Data Files or Software without prior - * written authorization of the copyright holder. - */ - -// Note: this file has been generated by a tool. - -package sun.text.resources; - -import sun.util.resources.OpenListResourceBundle; - -public class JavaTimeSupplementary extends OpenListResourceBundle { - @Override - protected final Object[][] getContents() { - final String[] sharedQuarterNames = { - "Q1", - "Q2", - "Q3", - "Q4", - }; - - final String[] sharedQuarterNarrows = { - "1", - "2", - "3", - "4", - }; - - final String[] sharedDatePatterns = { - "GGGG y MMMM d, EEEE", - "GGGG y MMMM d", - "GGGG y MMM d", - "G y-MM-dd", - }; - - final String[] sharedDayNames = { - "Sun", - "Mon", - "Tue", - "Wed", - "Thu", - "Fri", - "Sat", - }; - - final String[] sharedDayNarrows = { - "S", - "M", - "T", - "W", - "T", - "F", - "S", - }; - - final String[] sharedEras = { - "", - "AH", - }; - - final String[] sharedMonthNarrows = { - "1", - "2", - "3", - "4", - "5", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "", - }; - - final String[] sharedTimePatterns = { - "HH:mm:ss zzzz", - "HH:mm:ss z", - "HH:mm:ss", - "HH:mm", - }; - - final String[] sharedAmPmMarkers = { - "AM", - "PM", - }; - - final String[] sharedJavaTimeDatePatterns = { - "G y MMMM d, EEEE", - "G y MMMM d", - "G y MMM d", - "GGGGG y-MM-dd", - }; - - final String[] sharedJavaTimeLongEras = { - "", - "Meiji", - "Taisho", - "Showa", - "Heisei", - "Reiwa", - }; - - final String[] sharedShortEras = { - "Before R.O.C.", - "R.O.C.", - }; - - final String[] sharedMonthNames = { - "Jan", - "Feb", - "Mar", - "Apr", - "May", - "Jun", - "Jul", - "Aug", - "Sep", - "Oct", - "Nov", - "Dec", - "", - }; - - return new Object[][] { - { "QuarterAbbreviations", - sharedQuarterNames }, - { "QuarterNames", - sharedQuarterNames }, - { "QuarterNarrows", - sharedQuarterNarrows }, - { "field.dayperiod", - "Dayperiod" }, - { "field.era", - "Era" }, - { "field.hour", - "Hour" }, - { "field.minute", - "Minute" }, - { "field.month", - "Month" }, - { "field.second", - "Second" }, - { "field.week", - "Week" }, - { "field.weekday", - "Day of the Week" }, - { "field.year", - "Year" }, - { "field.zone", - "Zone" }, - { "islamic.DatePatterns", - sharedDatePatterns }, - { "islamic.DayAbbreviations", - sharedDayNames }, - { "islamic.DayNames", - sharedDayNames }, - { "islamic.DayNarrows", - sharedDayNarrows }, - { "islamic.Eras", - sharedEras }, - { "islamic.MonthAbbreviations", - new String[] { - "Muh.", - "Saf.", - "Rab. I", - "Rab. II", - "Jum. I", - "Jum. II", - "Raj.", - "Sha.", - "Ram.", - "Shaw.", - "Dhuʻl-Q.", - "Dhuʻl-H.", - "", - } - }, - { "islamic.MonthNames", - new String[] { - "Muharram", - "Safar", - "Rabiʻ I", - "Rabiʻ II", - "Jumada I", - "Jumada II", - "Rajab", - "Shaʻban", - "Ramadan", - "Shawwal", - "Dhuʻl-Qiʻdah", - "Dhuʻl-Hijjah", - "", - } - }, - { "islamic.MonthNarrows", - sharedMonthNarrows }, - { "islamic.QuarterNames", - sharedQuarterNames }, - { "islamic.QuarterNarrows", - sharedQuarterNarrows }, - { "islamic.TimePatterns", - sharedTimePatterns }, - { "islamic.abbreviated.AmPmMarkers", - sharedAmPmMarkers }, - { "islamic.long.Eras", - sharedEras }, - { "islamic.narrow.Eras", - sharedEras }, - { "islamic.short.Eras", - sharedEras }, - { "java.time.buddhist.DatePatterns", - sharedJavaTimeDatePatterns }, - { "java.time.buddhist.long.Eras", - new String[] { - "BC", - "BE", - } - }, - { "java.time.buddhist.short.Eras", - new String[] { - "BC", - "B.E.", - } - }, - { "java.time.islamic.DatePatterns", - sharedJavaTimeDatePatterns }, - { "java.time.japanese.DatePatterns", - new String[] { - "G y MMMM d (EEEE)", - "G y MMMM d", - "G y MMM d", - "GGGGGy.MM.dd", - } - }, - { "java.time.japanese.long.Eras", - sharedJavaTimeLongEras }, - { "java.time.japanese.short.Eras", - sharedJavaTimeLongEras }, - { "java.time.long.Eras", - new String[] { - "BCE", - "CE", - } - }, - { "java.time.roc.DatePatterns", - sharedJavaTimeDatePatterns }, - { "java.time.short.Eras", - new String[] { - "BC", - "AD", - } - }, - { "roc.AmPmMarkers", - sharedAmPmMarkers }, - { "roc.DatePatterns", - sharedDatePatterns }, - { "roc.DayNames", - sharedDayNames }, - { "roc.DayNarrows", - sharedDayNarrows }, - { "roc.Eras", - sharedShortEras }, - { "roc.MonthAbbreviations", - sharedMonthNames }, - { "roc.MonthNames", - sharedMonthNames }, - { "roc.MonthNarrows", - sharedMonthNarrows }, - { "roc.QuarterNames", - sharedQuarterNames }, - { "roc.QuarterNarrows", - sharedQuarterNarrows }, - { "roc.TimePatterns", - sharedTimePatterns }, - { "roc.abbreviated.AmPmMarkers", - sharedAmPmMarkers }, - { "roc.long.Eras", - sharedShortEras }, - { "roc.narrow.AmPmMarkers", - sharedAmPmMarkers }, - { "roc.narrow.Eras", - sharedShortEras }, - { "roc.short.Eras", - sharedShortEras }, - { "timezone.gmtFormat", - "GMT{0}" }, - { "timezone.hourFormat", - "+HH:mm;-HH:mm" }, - }; - } -} diff --git a/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementaryProvider.java b/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementaryProvider.java deleted file mode 100644 index 261e9803015..00000000000 --- a/src/java.base/share/classes/sun/text/resources/JavaTimeSupplementaryProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.text.resources; - -import java.util.spi.ResourceBundleProvider; - -/** - * An interface for the internal locale data provider for which {@code ResourceBundle} - * searches. - */ -public interface JavaTimeSupplementaryProvider extends ResourceBundleProvider { -} diff --git a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java index 4ae0275fdda..c539f57141e 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java +++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,6 @@ import jdk.internal.util.StaticProperty; import sun.util.resources.LocaleData; import sun.util.resources.OpenListResourceBundle; -import sun.util.resources.ParallelListResourceBundle; import sun.util.resources.TimeZoneNamesBundle; /** @@ -579,11 +578,7 @@ public String[] getCNPatterns(NumberFormat.Style formatStyle) { * resources required by JSR 310. */ public ResourceBundle getJavaTimeFormatData() { - ResourceBundle rb = localeData.getDateFormatData(locale); - if (rb instanceof ParallelListResourceBundle) { - localeData.setSupplementary((ParallelListResourceBundle) rb); - } - return rb; + return localeData.getDateFormatData(locale); } /** diff --git a/src/java.base/share/classes/sun/util/resources/LocaleData.java b/src/java.base/share/classes/sun/util/resources/LocaleData.java index 7bf14343531..20e8e0f8fe9 100644 --- a/src/java.base/share/classes/sun/util/resources/LocaleData.java +++ b/src/java.base/share/classes/sun/util/resources/LocaleData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,6 @@ import java.util.List; import java.util.Locale; import java.util.Map; -import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -143,30 +142,6 @@ public ResourceBundle getDateFormatData(Locale locale) { return getBundle(type.getTextResourcesPackage() + ".FormatData", locale); } - public void setSupplementary(ParallelListResourceBundle formatData) { - if (!formatData.areParallelContentsComplete()) { - String suppName = type.getTextResourcesPackage() + ".JavaTimeSupplementary"; - setSupplementary(suppName, formatData); - } - } - - private boolean setSupplementary(String suppName, ParallelListResourceBundle formatData) { - ParallelListResourceBundle parent = (ParallelListResourceBundle) formatData.getParent(); - boolean resetKeySet = false; - if (parent != null) { - resetKeySet = setSupplementary(suppName, parent); - } - OpenListResourceBundle supp = getSupplementary(suppName, formatData.getLocale()); - formatData.setParallelContents(supp); - resetKeySet |= supp != null; - // If any parents or this bundle has parallel data, reset keyset to create - // a new keyset with the data. - if (resetKeySet) { - formatData.resetKeySet(); - } - return resetKeySet; - } - /** * Gets a number format data resource bundle, using privileges * to allow accessing a sun.* package. @@ -179,18 +154,7 @@ public static ResourceBundle getBundle(final String baseName, final Locale local return Bundles.of(baseName, locale, LocaleDataStrategy.INSTANCE); } - private static OpenListResourceBundle getSupplementary(final String baseName, final Locale locale) { - OpenListResourceBundle rb = null; - try { - rb = (OpenListResourceBundle) Bundles.of(baseName, locale, - SupplementaryStrategy.INSTANCE); - } catch (MissingResourceException e) { - // return null if no supplementary is available - } - return rb; - } - - private abstract static class LocaleDataResourceBundleProvider + public abstract static class LocaleDataResourceBundleProvider implements ResourceBundleProvider { /** * Changes baseName to its module dependent package name and @@ -212,20 +176,6 @@ protected String toOtherBundleName(String baseName, String bundleName, Locale lo } } - /** - * A ResourceBundleProvider implementation for loading locale data - * resource bundles except for the java.time supplementary data. - */ - public abstract static class CommonResourceBundleProvider extends LocaleDataResourceBundleProvider { - } - - /** - * A ResourceBundleProvider implementation for loading supplementary - * resource bundles for java.time. - */ - public abstract static class SupplementaryResourceBundleProvider extends LocaleDataResourceBundleProvider { - } - // Bundles.Strategy implementations private static class LocaleDataStrategy implements Bundles.Strategy { @@ -254,18 +204,20 @@ public List getCandidateLocales(String baseName, Locale locale) { if (candidates == null) { LocaleProviderAdapter.Type type = baseName.contains(DOTCLDR) ? CLDR : JRE; LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type); - candidates = adapter instanceof ResourceBundleBasedAdapter ? - ((ResourceBundleBasedAdapter)adapter).getCandidateLocales(baseName, locale) : + candidates = adapter instanceof ResourceBundleBasedAdapter rbba ? + rbba.getCandidateLocales(baseName, locale) : defaultControl.getCandidateLocales(baseName, locale); // Weed out Locales which are known to have no resource bundles int lastDot = baseName.lastIndexOf('.'); String category = (lastDot >= 0) ? baseName.substring(lastDot + 1) : baseName; - Set langtags = ((JRELocaleProviderAdapter)adapter).getLanguageTagSet(category); - if (!langtags.isEmpty()) { - for (Iterator itr = candidates.iterator(); itr.hasNext();) { - if (!adapter.isSupportedProviderLocale(itr.next(), langtags)) { - itr.remove(); + if (adapter instanceof JRELocaleProviderAdapter jlpa) { + var langtags = jlpa.getLanguageTagSet(category); + if (!langtags.isEmpty()) { + for (Iterator itr = candidates.iterator(); itr.hasNext();) { + if (!jlpa.isSupportedProviderLocale(itr.next(), langtags)) { + itr.remove(); + } } } } @@ -302,36 +254,7 @@ public String toBundleName(String baseName, Locale locale) { public Class getResourceBundleProviderType(String baseName, Locale locale) { return inJavaBaseModule(baseName, locale) ? - null : CommonResourceBundleProvider.class; - } - } - - private static class SupplementaryStrategy extends LocaleDataStrategy { - private static final SupplementaryStrategy INSTANCE - = new SupplementaryStrategy(); - // TODO: avoid hard-coded Locales - private static final Set JAVA_BASE_LOCALES - = Set.of(Locale.ROOT, Locale.ENGLISH, Locale.US); - - private SupplementaryStrategy() { - } - - @Override - public List getCandidateLocales(String baseName, Locale locale) { - // Specify only the given locale - return List.of(locale); - } - - @Override - public Class getResourceBundleProviderType(String baseName, - Locale locale) { - return inJavaBaseModule(baseName, locale) ? - null : SupplementaryResourceBundleProvider.class; - } - - @Override - boolean inJavaBaseModule(String baseName, Locale locale) { - return JAVA_BASE_LOCALES.contains(locale); + null : LocaleDataResourceBundleProvider.class; } } } diff --git a/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java b/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java deleted file mode 100644 index 35319575010..00000000000 --- a/src/java.base/share/classes/sun/util/resources/ParallelListResourceBundle.java +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.util.resources; - -import java.util.AbstractSet; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashSet; -import java.util.Iterator; -import java.util.NoSuchElementException; -import java.util.ResourceBundle; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicMarkableReference; - -/** - * ParallelListResourceBundle is another variant of ListResourceBundle - * supporting "parallel" contents provided by another resource bundle - * (OpenListResourceBundle). Parallel contents, if any, are added into this - * bundle on demand. - * - * @author Masayoshi Okutsu - */ -public abstract class ParallelListResourceBundle extends ResourceBundle { - private volatile ConcurrentMap lookup; - private volatile Set keyset; - private final AtomicMarkableReference parallelContents - = new AtomicMarkableReference<>(null, false); - - /** - * Sole constructor. (For invocation by subclass constructors, typically - * implicit.) - */ - protected ParallelListResourceBundle() { - } - - /** - * Returns an array in which each item is a pair of objects in an - * Object array. The first element of each pair is the key, which - * must be a String, and the second element is the value - * associated with that key. See the class description for - * details. - * - * @return an array of an Object array representing a key-value pair. - */ - protected abstract Object[][] getContents(); - - /** - * Returns the parent of this resource bundle or null if there's no parent. - * - * @return the parent or null if no parent - */ - ResourceBundle getParent() { - return parent; - } - - /** - * Sets the parallel contents to the data given by rb. If rb is null, this - * bundle will be marked as `complete'. - * - * @param rb an OpenResourceBundle for parallel contents, or null indicating - * there are no parallel contents for this bundle - */ - public void setParallelContents(OpenListResourceBundle rb) { - if (rb == null) { - parallelContents.compareAndSet(null, null, false, true); - } else { - parallelContents.compareAndSet(null, rb.getContents(), false, false); - } - } - - /** - * Returns true if any parallel contents have been set or if this bundle is - * marked as complete. - * - * @return true if any parallel contents have been processed - */ - boolean areParallelContentsComplete() { - // Quick check for `complete' - if (parallelContents.isMarked()) { - return true; - } - boolean[] done = new boolean[1]; - Object[][] data = parallelContents.get(done); - return data != null || done[0]; - } - - @Override - protected Object handleGetObject(String key) { - if (key == null) { - throw new NullPointerException(); - } - - loadLookupTablesIfNecessary(); - return lookup.get(key); - } - - @Override - public Enumeration getKeys() { - return Collections.enumeration(keySet()); - } - - @Override - public boolean containsKey(String key) { - return keySet().contains(key); - } - - @Override - protected Set handleKeySet() { - loadLookupTablesIfNecessary(); - return lookup.keySet(); - } - - @Override - @SuppressWarnings("UnusedAssignment") - public Set keySet() { - Set ks; - while ((ks = keyset) == null) { - ks = new KeySet(handleKeySet(), parent); - synchronized (this) { - if (keyset == null) { - keyset = ks; - } - } - } - return ks; - } - - /** - * Discards any cached keyset value. This method is called from - * LocaleData for re-creating a KeySet. - */ - synchronized void resetKeySet() { - keyset = null; - } - - /** - * Loads the lookup table if they haven't been loaded already. - */ - void loadLookupTablesIfNecessary() { - ConcurrentMap map = lookup; - if (map == null) { - map = new ConcurrentHashMap<>(); - for (Object[] item : getContents()) { - map.put((String) item[0], item[1]); - } - } - - // If there's any parallel contents data, merge the data into map. - Object[][] data = parallelContents.getReference(); - if (data != null) { - for (Object[] item : data) { - map.putIfAbsent((String) item[0], item[1]); - } - parallelContents.set(null, true); - } - if (lookup == null) { - synchronized (this) { - if (lookup == null) { - lookup = map; - } - } - } - } - - /** - * This class implements the Set interface for - * ParallelListResourceBundle methods. - */ - private static class KeySet extends AbstractSet { - private final Set set; - private final ResourceBundle parent; - - private KeySet(Set set, ResourceBundle parent) { - this.set = set; - this.parent = parent; - } - - @Override - public boolean contains(Object o) { - if (set.contains(o)) { - return true; - } - return (parent != null) ? parent.containsKey((String) o) : false; - } - - @Override - public Iterator iterator() { - if (parent == null) { - return set.iterator(); - } - return new Iterator<>() { - private Iterator itr = set.iterator(); - private boolean usingParent; - - @Override - public boolean hasNext() { - if (itr.hasNext()) { - return true; - } - if (!usingParent) { - Set nextset = new HashSet<>(parent.keySet()); - nextset.removeAll(set); - itr = nextset.iterator(); - usingParent = true; - } - return itr.hasNext(); - } - - @Override - public String next() { - if (hasNext()) { - return itr.next(); - } - throw new NoSuchElementException(); - } - - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - }; - } - - @Override - public int size() { - if (parent == null) { - return set.size(); - } - Set allset = new HashSet<>(set); - allset.addAll(parent.keySet()); - return allset.size(); - } - } -} diff --git a/src/jdk.localedata/share/classes/module-info.java b/src/jdk.localedata/share/classes/module-info.java index 3705cf3137e..a04cf2f6f63 100644 --- a/src/jdk.localedata/share/classes/module-info.java +++ b/src/jdk.localedata/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,6 @@ provides sun.util.locale.provider.LocaleDataMetaInfo with sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo, sun.util.resources.provider.NonBaseLocaleDataMetaInfo; - provides sun.util.resources.LocaleData.CommonResourceBundleProvider with + provides sun.util.resources.LocaleData.LocaleDataResourceBundleProvider with sun.util.resources.provider.LocaleDataProvider; } diff --git a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData.java b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData.java index 0bbbd735f48..f393d5fd041 100644 --- a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData.java +++ b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,9 @@ package sun.text.resources.ext; -import sun.util.resources.ParallelListResourceBundle; +import sun.util.resources.OpenListResourceBundle; -public class FormatData extends ParallelListResourceBundle { +public class FormatData extends OpenListResourceBundle { /** * Exists to keep sun.text.resources.ext package alive * with IncludeLocales jlink plugin diff --git a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java index d9a3ebafe14..4ae7bf08a0a 100644 --- a/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java +++ b/src/jdk.localedata/share/classes/sun/text/resources/ext/FormatData_ja.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,11 +76,11 @@ package sun.text.resources.ext; -import sun.util.resources.ParallelListResourceBundle; +import sun.util.resources.OpenListResourceBundle; -public class FormatData_ja extends ParallelListResourceBundle { +public class FormatData_ja extends OpenListResourceBundle { /** - * Overrides ParallelListResourceBundle + * Overrides OpenListResourceBundle */ @Override protected final Object[][] getContents() { diff --git a/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java b/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java index 96041fea03f..c901af3a41b 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/provider/LocaleDataProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ /** * Service Provider for loading locale data resource bundles in jdk.localedata */ -public class LocaleDataProvider extends LocaleData.CommonResourceBundleProvider { +public class LocaleDataProvider extends LocaleData.LocaleDataResourceBundleProvider { @Override public ResourceBundle getBundle(String baseName, Locale locale) { var bundleName = toBundleName(baseName, locale); From ef4cbec6fba77fd84b328d333f8592c6eedf1a2d Mon Sep 17 00:00:00 2001 From: Mohamed Issa Date: Wed, 11 Jun 2025 17:47:03 +0000 Subject: [PATCH 010/213] 8358556: Assert when running with -XX:-UseLibmIntrinsic Reviewed-by: sviswanathan, kvn --- .../x86/templateInterpreterGenerator_x86_64.cpp | 14 ++++++++++---- src/hotspot/share/classfile/vmIntrinsics.cpp | 9 +++++++-- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp index 9ea4aeeccfa..46af93e9760 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86_64.cpp @@ -465,13 +465,19 @@ address TemplateInterpreterGenerator::generate_math_entry(AbstractInterpreter::M __ call_VM_leaf0(CAST_FROM_FN_PTR(address, SharedRuntime::dtan)); } } else if (kind == Interpreter::java_lang_math_tanh) { - assert(StubRoutines::dtanh() != nullptr, "not initialized"); + if (StubRoutines::dtanh() != nullptr) { __ movdbl(xmm0, Address(rsp, wordSize)); __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dtanh()))); + } else { + return nullptr; // Fallback to default implementation + } } else if (kind == Interpreter::java_lang_math_cbrt) { - assert(StubRoutines::dcbrt() != nullptr, "not initialized"); - __ movdbl(xmm0, Address(rsp, wordSize)); - __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dcbrt()))); + if (StubRoutines::dcbrt() != nullptr) { + __ movdbl(xmm0, Address(rsp, wordSize)); + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dcbrt()))); + } else { + return nullptr; // Fallback to default implementation + } } else if (kind == Interpreter::java_lang_math_abs) { assert(StubRoutines::x86::double_sign_mask() != nullptr, "not initialized"); __ movdbl(xmm0, Address(rsp, wordSize)); diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index 6fd5c07e137..baa945cdddf 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -289,8 +289,6 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_dsin: case vmIntrinsics::_dcos: case vmIntrinsics::_dtan: - case vmIntrinsics::_dtanh: - case vmIntrinsics::_dcbrt: case vmIntrinsics::_dlog: case vmIntrinsics::_dexp: case vmIntrinsics::_dpow: @@ -316,6 +314,13 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_fmaF: if (!InlineMathNatives || !UseFMA) return true; break; + case vmIntrinsics::_dtanh: + case vmIntrinsics::_dcbrt: + if (!InlineMathNatives || !InlineIntrinsics) return true; +#if defined(AMD64) && (defined(COMPILER1) || defined(COMPILER2)) + if (!UseLibmIntrinsic) return true; +#endif + break; case vmIntrinsics::_floatToFloat16: case vmIntrinsics::_float16ToFloat: if (!InlineIntrinsics) return true; From 429158218b52964ad1e79ba9d2fa5618d6b3398e Mon Sep 17 00:00:00 2001 From: Calvin Cheung Date: Wed, 11 Jun 2025 18:10:34 +0000 Subject: [PATCH 011/213] 8357382: runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java#aot fails with Xcomp and C1 Reviewed-by: iklam, kvn --- .../runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java index 30f7ce12ca0..0f7707edae3 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotClassLinking/BulkLoaderTest.java @@ -72,6 +72,7 @@ import java.lang.StackWalker.StackFrame; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -312,12 +313,15 @@ static void checkCustomLoader() throws Exception { } } + static ArrayList savedLoaders = new ArrayList<>(); + static Object initFromCustomLoader() throws Exception { String path = "cust.jar"; URL url = new File(path).toURI().toURL(); URL[] urls = new URL[] {url}; URLClassLoader urlClassLoader = new URLClassLoader("MyLoader", urls, null); + savedLoaders.add(urlClassLoader); Class c = Class.forName("SimpleCusty", true, urlClassLoader); return c.newInstance(); } From 8f733570040a7d7a24775e72244f47e946af191b Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Wed, 11 Jun 2025 18:51:54 +0000 Subject: [PATCH 012/213] 8358815: Exception event spec has stale reference to catch_klass parameter Reviewed-by: cjplummer, alanb --- src/hotspot/share/prims/jvmti.xml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/prims/jvmti.xml b/src/hotspot/share/prims/jvmti.xml index a15dbb5703a..fef71737c78 100644 --- a/src/hotspot/share/prims/jvmti.xml +++ b/src/hotspot/share/prims/jvmti.xml @@ -12862,16 +12862,17 @@ myInit() { parameters uniquely identify the current location (where the exception was detected) and allow the mapping to source file and line number when that information is - available. The exception field identifies the thrown + available. The exception parameter identifies the thrown exception object. The catch_method and catch_location identify the location of the catch clause, if any, that handles the thrown exception. If there is no such catch clause, - each field is set to 0. There is no guarantee that the thread will ever + the catch_method is set to null and the catch_locationis set to 0. + There is no guarantee that the thread will ever reach this catch clause. If there are native methods on the call stack between the throw location and the catch clause, the exception may be reset by one of those native methods. - Similarly, exceptions that are reported as uncaught (catch_klass - et al. set to 0) may in fact be caught by native code. + Similarly, exceptions that are reported as uncaught (catch_method + set to null) may in fact be caught by native code. Agents can check for these occurrences by monitoring events. Note that finally clauses are implemented as catch and re-throw. Therefore they @@ -12960,7 +12961,7 @@ myInit() { available. For exceptions caught in a Java programming language method, the exception object identifies the exception object. Exceptions caught in native methods are not necessarily available by the time the - exception catch is reported, so the exception field is set + exception catch is reported, so the exception parameter is set to null. jvmdi From 3b32f6a8ec37338764d3e6713247ff96e49bf5b3 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 12 Jun 2025 00:41:39 +0000 Subject: [PATCH 013/213] 8344556: [Graal] compiler/intrinsics/bmi/* fail when AOTCache cannot be loaded Reviewed-by: dnsimon, kvn --- test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java b/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java index b005d767287..9d2a731c6e5 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java +++ b/test/hotspot/jtreg/compiler/intrinsics/bmi/BMITestRunner.java @@ -122,10 +122,11 @@ public static OutputAnalyzer runTest(Class expr, List vmOpts = new LinkedList(); Collections.addAll(vmOpts, additionalVMOpts); - // Hide timestamps from warnings (e.g. due to potential CDS + // Hide timestamps from warnings (e.g. due to potential AOT // saved/runtime state mismatch), to avoid false positives when // comparing output across runs. vmOpts.add("-Xlog:all=warning:stdout:level,tags"); + vmOpts.add("-Xlog:aot=off"); //setup mode-specific options switch (testVMMode) { From d7aa34982053bad37b3b726539f1245d054258f4 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 12 Jun 2025 07:08:39 +0000 Subject: [PATCH 014/213] 8357826: Avoid running some jtreg tests when asan is configured Reviewed-by: sspitsyn, amitkumar, lmesnik, syan, lucy, cjplummer --- src/hotspot/share/prims/whitebox.cpp | 26 +++++++++++++++++++ src/hotspot/share/prims/whitebox.hpp | 5 +++- test/hotspot/jtreg/TEST.ROOT | 2 ++ .../TestUseCompressedOopsFlagsWithUlimit.java | 2 ++ .../Thread/TestBreakSignalThreadDump.java | 2 ++ .../runtime/XCheckJniJsig/XCheckJSig.java | 2 ++ .../dcmd/vm/SystemDumpMapTest.java | 2 ++ .../serviceability/dcmd/vm/SystemMapTest.java | 4 +++ test/jdk/TEST.ROOT | 2 ++ test/jdk/build/AbsPathsInImage.java | 4 ++- test/jtreg-ext/requires/VMProps.java | 11 ++++++++ test/lib/jdk/test/whitebox/WhiteBox.java | 4 +++ 12 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 374e877faa6..1507696c4d3 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -1075,6 +1075,22 @@ bool WhiteBox::validate_cgroup(bool cgroups_v2_enabled, } #endif +bool WhiteBox::is_asan_enabled() { +#ifdef ADDRESS_SANITIZER + return true; +#else + return false; +#endif +} + +bool WhiteBox::is_ubsan_enabled() { +#ifdef UNDEFINED_BEHAVIOR_SANITIZER + return true; +#else + return false; +#endif +} + bool WhiteBox::compile_method(Method* method, int comp_level, int bci, JavaThread* THREAD) { // Screen for unavailable/bad comp level or null method AbstractCompiler* comp = CompileBroker::compiler(comp_level); @@ -1886,6 +1902,14 @@ WB_ENTRY(jboolean, WB_IsMonitorInflated(JNIEnv* env, jobject wb, jobject obj)) return (jboolean) obj_oop->mark().has_monitor(); WB_END +WB_ENTRY(jboolean, WB_IsAsanEnabled(JNIEnv* env)) + return (jboolean) WhiteBox::is_asan_enabled(); +WB_END + +WB_ENTRY(jboolean, WB_IsUbsanEnabled(JNIEnv* env)) + return (jboolean) WhiteBox::is_ubsan_enabled(); +WB_END + WB_ENTRY(jlong, WB_getInUseMonitorCount(JNIEnv* env, jobject wb)) return (jlong) WhiteBox::get_in_use_monitor_count(); WB_END @@ -2882,6 +2906,8 @@ static JNINativeMethod methods[] = { (void*)&WB_AddModuleExportsToAll }, {CC"deflateIdleMonitors", CC"()Z", (void*)&WB_DeflateIdleMonitors }, {CC"isMonitorInflated0", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsMonitorInflated }, + {CC"isAsanEnabled", CC"()Z", (void*)&WB_IsAsanEnabled }, + {CC"isUbsanEnabled", CC"()Z", (void*)&WB_IsUbsanEnabled }, {CC"getInUseMonitorCount", CC"()J", (void*)&WB_getInUseMonitorCount }, {CC"getLockStackCapacity", CC"()I", (void*)&WB_getLockStackCapacity }, {CC"supportsRecursiveLightweightLocking", CC"()Z", (void*)&WB_supportsRecursiveLightweightLocking }, diff --git a/src/hotspot/share/prims/whitebox.hpp b/src/hotspot/share/prims/whitebox.hpp index 4ba684fc09a..c20d35abbbb 100644 --- a/src/hotspot/share/prims/whitebox.hpp +++ b/src/hotspot/share/prims/whitebox.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,6 +72,9 @@ class WhiteBox : public AllStatic { #ifdef LINUX static bool validate_cgroup(bool cgroups_v2_enabled, const char* controllers_file, const char* proc_self_cgroup, const char* proc_self_mountinfo, u1* cg_flags); #endif + // provide info about enabling of Address Sanitizer / Undefined Behavior Sanitizer + static bool is_asan_enabled(); + static bool is_ubsan_enabled(); }; #endif // SHARE_PRIMS_WHITEBOX_HPP diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index 8f4ef153907..9071dfa2fbf 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -91,6 +91,8 @@ requires.properties= \ vm.compiler1.enabled \ vm.compiler2.enabled \ vm.musl \ + vm.asan \ + vm.ubsan \ vm.flagless \ container.support \ systemd.support \ diff --git a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java index 40d83739ef5..40f607bf8a1 100644 --- a/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java +++ b/test/hotspot/jtreg/gc/arguments/TestUseCompressedOopsFlagsWithUlimit.java @@ -31,6 +31,8 @@ * @library /test/lib * @library / * @requires vm.bits == "64" + * @comment ulimit clashes with the memory requirements of ASAN + * @requires !vm.asan * @requires os.family == "linux" * @requires vm.gc != "Z" * @requires vm.opt.UseCompressedOops == null diff --git a/test/hotspot/jtreg/runtime/Thread/TestBreakSignalThreadDump.java b/test/hotspot/jtreg/runtime/Thread/TestBreakSignalThreadDump.java index b985e15bd17..011f6979431 100644 --- a/test/hotspot/jtreg/runtime/Thread/TestBreakSignalThreadDump.java +++ b/test/hotspot/jtreg/runtime/Thread/TestBreakSignalThreadDump.java @@ -38,6 +38,8 @@ * @requires os.family != "windows" & os.family != "aix" * @comment TODO: Decide libjsig support on static JDK with 8351367 * @requires !jdk.static + * @comment loading of the jsig lib does currently not work well with ASAN lib + * @requires !vm.asan * @library /vmTestbase * /test/lib * @run driver TestBreakSignalThreadDump load_libjsig diff --git a/test/hotspot/jtreg/runtime/XCheckJniJsig/XCheckJSig.java b/test/hotspot/jtreg/runtime/XCheckJniJsig/XCheckJSig.java index a8010506d96..6dbe42cebb0 100644 --- a/test/hotspot/jtreg/runtime/XCheckJniJsig/XCheckJSig.java +++ b/test/hotspot/jtreg/runtime/XCheckJniJsig/XCheckJSig.java @@ -29,6 +29,8 @@ * @modules java.base/jdk.internal.misc * java.management * @requires os.family == "linux" | os.family == "mac" + * @comment loading of the jsig lib does currently not work well with ASAN lib + * @requires !vm.asan * @comment TODO: Decide libjsig support on static JDK with 8351367 * @requires !jdk.static * @run driver XCheckJSig diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/SystemDumpMapTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/SystemDumpMapTest.java index 1911862b361..8b8ed0b53ab 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/vm/SystemDumpMapTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/SystemDumpMapTest.java @@ -36,6 +36,8 @@ * @summary Test of diagnostic command System.map * @library /test/lib * @requires (os.family == "linux" | os.family == "windows" | os.family == "mac") + * @comment ASAN changes the memory map dump slightly, but the test has rather strict requirements + * @requires !vm.asan * @requires os.arch != "riscv64" | !(vm.cpu.features ~= ".*qemu.*") * @modules java.base/jdk.internal.misc * java.compiler diff --git a/test/hotspot/jtreg/serviceability/dcmd/vm/SystemMapTest.java b/test/hotspot/jtreg/serviceability/dcmd/vm/SystemMapTest.java index 283dd4bae72..dcc451d41be 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/vm/SystemMapTest.java +++ b/test/hotspot/jtreg/serviceability/dcmd/vm/SystemMapTest.java @@ -32,6 +32,8 @@ * @summary Test of diagnostic command System.map * @library /test/lib * @requires (vm.gc != "Z") & (os.family == "linux" | os.family == "windows" | os.family == "mac") + * @comment ASAN changes the memory map dump slightly, but the test has rather strict requirements + * @requires !vm.asan * @modules java.base/jdk.internal.misc * java.compiler * java.management @@ -47,6 +49,8 @@ * @summary Test of diagnostic command System.map using ZGC * @library /test/lib * @requires vm.gc.Z & (os.family == "linux" | os.family == "windows" | os.family == "mac") + * @comment ASAN changes the memory map dump slightly, but the test has rather strict requirements + * @requires !vm.asan * @modules java.base/jdk.internal.misc * java.compiler * java.management diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 97efc340019..0fa78bebc3f 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -102,6 +102,8 @@ requires.properties= \ vm.cds.write.archived.java.heap \ vm.continuations \ vm.musl \ + vm.asan \ + vm.ubsan \ vm.debug \ vm.hasSA \ vm.hasJFR \ diff --git a/test/jdk/build/AbsPathsInImage.java b/test/jdk/build/AbsPathsInImage.java index 7821b60670a..1aa7e59941e 100644 --- a/test/jdk/build/AbsPathsInImage.java +++ b/test/jdk/build/AbsPathsInImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,8 @@ * @bug 8226346 * @summary Check all output files for absolute path fragments * @requires !vm.debug + * @comment ASAN keeps the 'unwanted' paths in the binaries because of its build options + * @requires !vm.asan * @run main/othervm -Xmx900m AbsPathsInImage */ public class AbsPathsInImage { diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 360c96c74ef..3c7a81cd2fa 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -138,6 +138,8 @@ public Map call() { map.put("container.support", this::containerSupport); map.put("systemd.support", this::systemdSupport); map.put("vm.musl", this::isMusl); + map.put("vm.asan", this::isAsanEnabled); + map.put("vm.ubsan", this::isUbsanEnabled); map.put("release.implementor", this::implementor); map.put("jdk.containerized", this::jdkContainerized); map.put("vm.flagless", this::isFlagless); @@ -728,6 +730,15 @@ protected String isMusl() { return Boolean.toString(WB.getLibcName().contains("musl")); } + // Sanitizer support + protected String isAsanEnabled() { + return "" + WB.isAsanEnabled(); + } + + protected String isUbsanEnabled() { + return "" + WB.isUbsanEnabled(); + } + private String implementor() { try (InputStream in = new BufferedInputStream(new FileInputStream( System.getProperty("java.home") + "/release"))) { diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index d1f2c5822af..f3d9ba7b6e9 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -322,6 +322,10 @@ public Object[] parseCommandLine(String commandline, char delim, Dia public native void NMTFreeArena(long arena); public native void NMTArenaMalloc(long arena, long size); + // Sanitizers + public native boolean isAsanEnabled(); + public native boolean isUbsanEnabled(); + // Compiler // Determines if the libgraal shared library file is present. From 5886ef728fc1efe43e90e056c03725c3ee982ad6 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Thu, 12 Jun 2025 07:51:29 +0000 Subject: [PATCH 015/213] 8359182: Use @requires instead of SkippedException for MaxPath.java Reviewed-by: bpb, bchristi --- test/jdk/java/io/File/MaxPath.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/test/jdk/java/io/File/MaxPath.java b/test/jdk/java/io/File/MaxPath.java index 269b291709c..30951ac0d85 100644 --- a/test/jdk/java/io/File/MaxPath.java +++ b/test/jdk/java/io/File/MaxPath.java @@ -24,21 +24,14 @@ /* @test @bug 6481955 @summary Path length less than MAX_PATH (260) works on Windows - @library /test/lib + @requires (os.family == "windows") */ import java.io.File; import java.io.IOException; -import jtreg.SkippedException; - public class MaxPath { public static void main(String[] args) throws Exception { - String osName = System.getProperty("os.name"); - if (!osName.startsWith("Windows")) { - throw new SkippedException("This test is run only on Windows"); - } - int MAX_PATH = 260; String dir = new File(".").getAbsolutePath() + "\\"; String padding = "1234567890123456789012345678901234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890012345678900123456789001234567890"; From 7b7136b4eca15693cfcd46ae63d644efc8a88d2c Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Thu, 12 Jun 2025 08:10:27 +0000 Subject: [PATCH 016/213] 8359181: Error messages generated by configure --help after 8301197 Reviewed-by: erikj, ihse --- make/autoconf/configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/autoconf/configure b/make/autoconf/configure index 443a37bae77..98126d1558d 100644 --- a/make/autoconf/configure +++ b/make/autoconf/configure @@ -1,6 +1,6 @@ #!/bin/bash # -# Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -366,7 +366,7 @@ EOT # Print additional help, e.g. a list of toolchains and JVM features. # This must be done by the autoconf script. - ( CONFIGURE_PRINT_ADDITIONAL_HELP=true . $generated_script PRINTF=printf ) + ( CONFIGURE_PRINT_ADDITIONAL_HELP=true . $generated_script PRINTF=printf ECHO=echo ) cat < Date: Thu, 12 Jun 2025 08:18:00 +0000 Subject: [PATCH 017/213] 8359083: Test jdkCheckHtml.java should report SkippedException rather than report fails when miss tidy Reviewed-by: hannesw --- test/docs/jdk/javadoc/doccheck/DocCheck.java | 5 ++++- test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java | 4 ++-- .../doccheck/doccheckutils/checkers/TidyChecker.java | 6 +++--- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/test/docs/jdk/javadoc/doccheck/DocCheck.java b/test/docs/jdk/javadoc/doccheck/DocCheck.java index acd61b0e76e..5819f641d6e 100644 --- a/test/docs/jdk/javadoc/doccheck/DocCheck.java +++ b/test/docs/jdk/javadoc/doccheck/DocCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -140,6 +140,9 @@ public void init() { var baseDir = DOCS_DIR.resolve(DIR); fileTester.processFiles(baseDir); files = fileTester.getFiles(); + if (html) { + new TidyChecker(); + } } public List getCheckers() { diff --git a/test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java b/test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java index 3e9f3ab9f82..fdf6ab7e78d 100644 --- a/test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java +++ b/test/docs/jdk/javadoc/doccheck/checks/jdkCheckHtml.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,6 @@ * @bug 8337109 * @summary Check the html in the generated documentation * @library /test/langtools/tools/lib ../../doccheck /test/lib ../../../../tools/tester - * @build DocTester toolbox.TestRunner + * @build DocTester toolbox.TestRunner jtreg.SkippedException * @run main/othervm -Ddoccheck.checks=html DocCheck */ diff --git a/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/TidyChecker.java b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/TidyChecker.java index 727e90a76e3..36a6a4a7b7a 100644 --- a/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/TidyChecker.java +++ b/test/docs/jdk/javadoc/doccheck/doccheckutils/checkers/TidyChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,7 @@ import java.util.regex.Pattern; import java.util.stream.Collectors; import java.util.stream.Stream; +import jtreg.SkippedException; public class TidyChecker implements FileChecker, AutoCloseable { private final Path TIDY; @@ -164,8 +165,7 @@ private Path initTidy() { if (p.isPresent()) { tidyExePath = p.get(); } else { - System.err.println("tidy not found on PATH"); - return Path.of("tidy"); //non-null placeholder return; exception would be better + throw new jtreg.SkippedException("tidy not found on PATH"); } } From 3f0fef2c9c323cb7b6e9191b17eac4296ff22dac Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Thu, 12 Jun 2025 08:54:21 +0000 Subject: [PATCH 018/213] 8359135: New test TestCPUTimeSampleThrottling fails intermittently Reviewed-by: mdoerr --- .../TestCPUTimeSampleThrottling.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java index 55b350ad096..b0b9d6d2be7 100644 --- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java +++ b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleThrottling.java @@ -61,19 +61,27 @@ private static void testThrottleSettings() throws Exception { private static void testThrottleSettingsPeriod() throws Exception { float rate = countEvents(1000, "10ms").rate(); - Asserts.assertTrue(rate > 90 && rate < 110, "Expected around 100 events per second, got " + rate); + Asserts.assertTrue(rate > 75 && rate < 110, "Expected around 100 events per second, got " + rate); } - private record EventCount(long count, float time) { + private record EventCount(long count, float cpuTime) { float rate() { - return count / time; + return count / cpuTime; } } - private static EventCount countEvents(int timeMs, String rate) throws Exception { - try(Recording recording = new Recording()) { + /** + * Counting the events that are emitted for a given throttle in a given time. + *

+ * The result is wall-clock independent; it only records the CPU-time and the number of + * emitted events. The result, therefore, does not depend on the load of the machine. + * And because failed events are counted too, the result is not affected by the thread + * doing other in-JVM work (like garbage collection). + */ + private static EventCount countEvents(int timeMs, String throttle) throws Exception { + try (Recording recording = new Recording()) { recording.enable(EventNames.CPUTimeSample) - .with("throttle", rate); + .with("throttle", throttle); var bean = ManagementFactory.getThreadMXBean(); @@ -92,8 +100,6 @@ private static EventCount countEvents(int timeMs, String rate) throws Exception .equals(Thread.currentThread().getName())) .count(); - System.out.println("Event count: " + eventCount + ", CPU time: " + spendCPUTime / 1_000_000_000f + "s"); - return new EventCount(eventCount, spendCPUTime / 1_000_000_000f); } } From 65e63b6ab4241fc9d683e2ffa5bfe6e1a30059b6 Mon Sep 17 00:00:00 2001 From: Anjian Wen Date: Thu, 12 Jun 2025 10:44:47 +0000 Subject: [PATCH 019/213] 8359218: RISC-V: Only enable CRC32 intrinsic when AvoidUnalignedAccess == false Reviewed-by: fyang, fjiang --- src/hotspot/cpu/riscv/vm_version_riscv.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index eca1bb83ab6..947d78477da 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -203,15 +203,15 @@ void VM_Version::common_initialize() { } } - // Misc Intrinsics could depend on RVV + // Misc Intrinsics that could depend on RVV. - if (UseZba || UseRVV) { + if (!AvoidUnalignedAccesses && (UseZba || UseRVV)) { if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { FLAG_SET_DEFAULT(UseCRC32Intrinsics, true); } } else { if (!FLAG_IS_DEFAULT(UseCRC32Intrinsics)) { - warning("CRC32 intrinsic requires Zba or RVV instructions (not available on this CPU)"); + warning("CRC32 intrinsic are not available on this CPU."); } FLAG_SET_DEFAULT(UseCRC32Intrinsics, false); } From b6ec93b038c411d0c49be671c3b44dd231d01305 Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Thu, 12 Jun 2025 11:40:31 +0000 Subject: [PATCH 020/213] 8359121: C2: Region added by vectorizedMismatch intrinsic can survive as a dead node after IGVN Reviewed-by: thartmann, chagedorn --- src/hotspot/share/opto/library_call.cpp | 4 ++ ...RegionFromVectorizedMismatchIntrinsic.java | 54 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/igvn/RemoveDeadRegionFromVectorizedMismatchIntrinsic.java diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 29f737bce08..e9878cc0c77 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -6580,6 +6580,10 @@ bool LibraryCallKit::inline_vectorizedMismatch() { memory_phi = _gvn.transform(memory_phi); result_phi = _gvn.transform(result_phi); + record_for_igvn(exit_block); + record_for_igvn(memory_phi); + record_for_igvn(result_phi); + set_control(exit_block); set_all_memory(memory_phi); set_result(result_phi); diff --git a/test/hotspot/jtreg/compiler/igvn/RemoveDeadRegionFromVectorizedMismatchIntrinsic.java b/test/hotspot/jtreg/compiler/igvn/RemoveDeadRegionFromVectorizedMismatchIntrinsic.java new file mode 100644 index 00000000000..e2f0bbf547a --- /dev/null +++ b/test/hotspot/jtreg/compiler/igvn/RemoveDeadRegionFromVectorizedMismatchIntrinsic.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8359121 + * @summary Region node introduced by ArraysSupport.mismatch must be disconnected, + * and not just put aside as dead: when simplifying + * Proj -> Region -> If -> ... + * into + * Proj -> If -> ... + * -> Region + * the dead Region node must be removed from Proj's outputs. + * @modules java.base/jdk.internal.util + * @run main/othervm -Xcomp + * -XX:CompileCommand=compileonly,compiler.igvn.RemoveDeadRegionFromVectorizedMismatchIntrinsic::test + * compiler.igvn.RemoveDeadRegionFromVectorizedMismatchIntrinsic + * @run main compiler.igvn.RemoveDeadRegionFromVectorizedMismatchIntrinsic + */ +package compiler.igvn; + +import jdk.internal.util.ArraysSupport; + +public class RemoveDeadRegionFromVectorizedMismatchIntrinsic { + public static void main(String[] args) { + ArraysSupport.mismatch(new int[0], new int[0], 0); // loads ArraysSupport + test(new byte[0], new byte[0]); + } + + public static int test(byte[] a, byte[] b) { + int i = ArraysSupport.vectorizedMismatch(a, 0, b, 0, 0, 0); + return i >= 0 ? i : 0; + } +} From 91fdd72c97ab109c08893e5b613cbe4412b645aa Mon Sep 17 00:00:00 2001 From: kabutz Date: Thu, 12 Jun 2025 11:44:04 +0000 Subject: [PATCH 021/213] 8355726: LinkedBlockingDeque fixes and improvements Reviewed-by: vklang, dl --- .../util/concurrent/LinkedBlockingDeque.java | 60 +++++----- .../tck/LinkedBlockingDequeTest.java | 110 ++++++++++++++++++ 2 files changed, 142 insertions(+), 28 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java index 8d0bc7ccdde..1e3ffb81150 100644 --- a/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java +++ b/src/java.base/share/classes/java/util/concurrent/LinkedBlockingDeque.java @@ -150,7 +150,7 @@ static final class Node { transient Node last; /** Number of items in the deque */ - private transient int count; + private transient volatile int count; /** @serial Maximum number of items in the deque */ private final int capacity; @@ -206,10 +206,13 @@ public LinkedBlockingDeque(Collection c) { /** * Links node as first element, or returns false if full. + * + * @return true if the node was added; false otherwise */ private boolean linkFirst(Node node) { // assert lock.isHeldByCurrentThread(); - if (count >= capacity) + int c; + if ((c = count) >= capacity) return false; Node f = first; node.next = f; @@ -218,17 +221,20 @@ private boolean linkFirst(Node node) { last = node; else f.prev = node; - ++count; + count = c + 1; notEmpty.signal(); return true; } /** * Links node as last element, or returns false if full. + * + * @return true if the node was added; false otherwise */ private boolean linkLast(Node node) { // assert lock.isHeldByCurrentThread(); - if (count >= capacity) + int c; + if ((c = count) >= capacity) return false; Node l = last; node.prev = l; @@ -237,7 +243,7 @@ private boolean linkLast(Node node) { first = node; else l.next = node; - ++count; + count = c + 1; notEmpty.signal(); return true; } @@ -334,6 +340,8 @@ public void addLast(E e) { */ public boolean offerFirst(E e) { if (e == null) throw new NullPointerException(); + if (count >= capacity) + return false; Node node = new Node(e); final ReentrantLock lock = this.lock; lock.lock(); @@ -349,6 +357,8 @@ public boolean offerFirst(E e) { */ public boolean offerLast(E e) { if (e == null) throw new NullPointerException(); + if (count >= capacity) + return false; Node node = new Node(e); final ReentrantLock lock = this.lock; lock.lock(); @@ -367,7 +377,7 @@ public void putFirst(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); Node node = new Node(e); final ReentrantLock lock = this.lock; - lock.lock(); + lock.lockInterruptibly(); try { while (!linkFirst(node)) notFull.await(); @@ -384,7 +394,7 @@ public void putLast(E e) throws InterruptedException { if (e == null) throw new NullPointerException(); Node node = new Node(e); final ReentrantLock lock = this.lock; - lock.lock(); + lock.lockInterruptibly(); try { while (!linkLast(node)) notFull.await(); @@ -458,6 +468,7 @@ public E removeLast() { } public E pollFirst() { + if (count == 0) return null; final ReentrantLock lock = this.lock; lock.lock(); try { @@ -468,6 +479,7 @@ public E pollFirst() { } public E pollLast() { + if (count == 0) return null; final ReentrantLock lock = this.lock; lock.lock(); try { @@ -479,7 +491,7 @@ public E pollLast() { public E takeFirst() throws InterruptedException { final ReentrantLock lock = this.lock; - lock.lock(); + lock.lockInterruptibly(); try { E x; while ( (x = unlinkFirst()) == null) @@ -492,7 +504,7 @@ public E takeFirst() throws InterruptedException { public E takeLast() throws InterruptedException { final ReentrantLock lock = this.lock; - lock.lock(); + lock.lockInterruptibly(); try { E x; while ( (x = unlinkLast()) == null) @@ -558,6 +570,7 @@ public E getLast() { } public E peekFirst() { + if (count == 0) return null; final ReentrantLock lock = this.lock; lock.lock(); try { @@ -568,6 +581,7 @@ public E peekFirst() { } public E peekLast() { + if (count == 0) return null; final ReentrantLock lock = this.lock; lock.lock(); try { @@ -718,13 +732,7 @@ public E peek() { * insert or remove an element. */ public int remainingCapacity() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return capacity - count; - } finally { - lock.unlock(); - } + return capacity - count; } /** @@ -806,13 +814,7 @@ public boolean remove(Object o) { * @return the number of elements in this deque */ public int size() { - final ReentrantLock lock = this.lock; - lock.lock(); - try { - return count; - } finally { - lock.unlock(); - } + return count; } /** @@ -858,7 +860,7 @@ public boolean addAll(Collection c) { // Copy c into a private chain of Nodes Node beg = null, end = null; - int n = 0; + long n = 0; for (E e : c) { Objects.requireNonNull(e); n++; @@ -878,14 +880,15 @@ public boolean addAll(Collection c) { final ReentrantLock lock = this.lock; lock.lock(); try { - if (count + n <= capacity) { + long cnt; + if ((cnt = count + n) <= capacity) { beg.prev = last; if (first == null) first = beg; else last.next = beg; last = end; - count += n; + count = (int)cnt; notEmpty.signalAll(); return true; } @@ -894,6 +897,7 @@ public boolean addAll(Collection c) { } // Fall back to historic non-atomic implementation, failing // with IllegalStateException when the capacity is exceeded. + beg = end = null; // help GC return super.addAll(c); } @@ -994,8 +998,8 @@ public void clear() { for (Node f = first; f != null; ) { f.item = null; Node n = f.next; - f.prev = null; - f.next = null; + f.prev = f; + f.next = f; f = n; } first = last = null; diff --git a/test/jdk/java/util/concurrent/tck/LinkedBlockingDequeTest.java b/test/jdk/java/util/concurrent/tck/LinkedBlockingDequeTest.java index 02b1b67d643..e8775b868f2 100644 --- a/test/jdk/java/util/concurrent/tck/LinkedBlockingDequeTest.java +++ b/test/jdk/java/util/concurrent/tck/LinkedBlockingDequeTest.java @@ -43,8 +43,10 @@ import java.util.concurrent.BlockingDeque; import java.util.concurrent.BlockingQueue; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingDeque; import junit.framework.Test; @@ -1886,4 +1888,112 @@ public void testNeverContainsNull() { } } + public void testInterruptedExceptionThrownInBlockingMethods() throws InterruptedException { + // Ensure that putFirst(), putLast(), takeFirst(), and takeLast() + // immediately throw an InterruptedException if the thread is + // interrupted, to be consistent with other blocking queues such as + // ArrayBlockingQueue and LinkedBlockingQueue + try (var pool = Executors.newSingleThreadExecutor()) { + Future success = pool.submit(() -> { + var queue = new LinkedBlockingDeque<>(); + Thread.currentThread().interrupt(); + try { + queue.putFirst(42); + fail("Expected InterruptedException in putFirst()"); + } catch (InterruptedException expected) { + // good that's what we want + assertFalse(Thread.currentThread().isInterrupted()); + } + + Thread.currentThread().interrupt(); + try { + queue.putLast(42); + fail("Expected InterruptedException in putLast()"); + } catch (InterruptedException expected) { + // good that's what we want + assertFalse(Thread.currentThread().isInterrupted()); + } + + queue.add(42); + Thread.currentThread().interrupt(); + try { + queue.takeFirst(); + fail("Expected InterruptedException in takeFirst()"); + } catch (InterruptedException expected) { + // good that's what we want + assertFalse(Thread.currentThread().isInterrupted()); + } + + queue.add(42); + Thread.currentThread().interrupt(); + try { + queue.takeLast(); + fail("Expected InterruptedException in takeLast()"); + } catch (InterruptedException expected) { + // good that's what we want + assertFalse(Thread.currentThread().isInterrupted()); + } + return null; + }); + try { + success.get(); + } catch (ExecutionException e) { + try { + throw e.getCause(); + } catch (Error | RuntimeException unchecked) { + throw unchecked; + } catch (Throwable cause) { + throw new AssertionError(cause); + } + } + } + } + + public void testWeaklyConsistentIterationWithClear() { + final LinkedBlockingDeque q = new LinkedBlockingDeque<>(); + q.add(one); + q.add(two); + q.add(three); + final Iterator it = q.iterator(); + mustEqual(one, it.next()); + q.clear(); + q.add(four); + q.add(five); + q.add(six); + mustEqual(two, it.next()); + mustEqual(four, it.next()); + mustEqual(five, it.next()); + mustEqual(six, it.next()); + mustEqual(3, q.size()); + } + + public void testWeaklyConsistentIterationWithIteratorRemove() { + final LinkedBlockingDeque q = new LinkedBlockingDeque<>(); + q.add(one); + q.add(two); + q.add(three); + q.add(four); + q.add(five); + final Iterator it1 = q.iterator(); + final Iterator it2 = q.iterator(); + final Iterator it3 = q.iterator(); + mustEqual(one, it1.next()); + mustEqual(two, it1.next()); + it1.remove(); // removing "two" + mustEqual(one, it2.next()); + it2.remove(); // removing "one" + mustEqual(three, it2.next()); + mustEqual(four, it2.next()); + it2.remove(); // removing "four" + mustEqual(one, it3.next()); + mustEqual(three, it3.next()); + mustEqual(five, it3.next()); + assertFalse(it3.hasNext()); + mustEqual(three, it1.next()); + mustEqual(five, it1.next()); + assertFalse(it1.hasNext()); + mustEqual(five, it2.next()); + assertFalse(it2.hasNext()); + mustEqual(2, q.size()); + } } From e5ce5c57c83972ff52758a804c942986cab74ca7 Mon Sep 17 00:00:00 2001 From: Rohitash Kumar Date: Thu, 12 Jun 2025 12:23:42 +0000 Subject: [PATCH 022/213] 8357959: (bf) ByteBuffer.allocateDirect initialization can result in large TTSP spikes Reviewed-by: shade, alanb --- .../share/classes/java/nio/Bits.java | 26 +++++++- .../java/nio/Direct-X-Buffer.java.template | 4 +- .../java/nio/Buffer/AllocateDirectInit.java | 59 +++++++++++++----- .../bench/java/nio/DirectByteBufferAlloc.java | 60 +++++++++++++++++++ 4 files changed, 132 insertions(+), 17 deletions(-) create mode 100644 test/micro/org/openjdk/bench/java/nio/DirectByteBufferAlloc.java diff --git a/src/java.base/share/classes/java/nio/Bits.java b/src/java.base/share/classes/java/nio/Bits.java index b11cb4947db..a9a22d6079e 100644 --- a/src/java.base/share/classes/java/nio/Bits.java +++ b/src/java.base/share/classes/java/nio/Bits.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -234,4 +234,28 @@ public long getMemoryUsed() { // of an element by element copy. These numbers may change over time. static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6; + + // Maximum number of bytes to set in one call to {@code Unsafe.setMemory}. + // This threshold allows safepoint polling during large memory operations. + static final long UNSAFE_SET_THRESHOLD = 1024 * 1024; + + /** + * Sets a block of memory starting from a given address to a specified byte value. + * + * @param srcAddr + * the starting memory address + * @param count + * the number of bytes to set + * @param value + * the byte value to set + */ + static void setMemory(long srcAddr, long count, byte value) { + long offset = 0; + while (offset < count) { + long len = Math.min(UNSAFE_SET_THRESHOLD, count - offset); + UNSAFE.setMemory(srcAddr + offset, len, value); + offset += len; + } + } + } diff --git a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index 0da1dc66a9a..580109a2eb0 100644 --- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,7 +114,7 @@ class Direct$Type$Buffer$RW$$BO$ Bits.unreserveMemory(size, cap); throw x; } - UNSAFE.setMemory(base, size, (byte) 0); + Bits.setMemory(base, size, (byte) 0); if (pa && (base % ps != 0)) { // Round up to page boundary address = base + ps - (base & (ps - 1)); diff --git a/test/jdk/java/nio/Buffer/AllocateDirectInit.java b/test/jdk/java/nio/Buffer/AllocateDirectInit.java index c54536df8ba..472187fdcda 100644 --- a/test/jdk/java/nio/Buffer/AllocateDirectInit.java +++ b/test/jdk/java/nio/Buffer/AllocateDirectInit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,29 +23,60 @@ /** * @test - * @bug 4490253 6535542 + * @bug 4490253 6535542 8357959 + * @key randomness + * @library /test/lib + * @build jdk.test.lib.RandomFactory * @summary Verify that newly allocated direct buffers are initialized. + * @run main/othervm AllocateDirectInit */ import java.nio.ByteBuffer; +import java.util.Random; + +import jdk.test.lib.RandomFactory; public class AllocateDirectInit { + private static final int MAX_BIN_LIMIT = 16 * 1024 * 1024; + private static final int MAX_DEC_LIMIT = 10 * 1000 * 1000; + private static final int TRIES_PER_LIMIT = 1024; + + private static final Random RND = RandomFactory.getRandom(); + public static void main(String [] args){ - for (int i = 0; i < 1024; i++) { - ByteBuffer bb = ByteBuffer.allocateDirect(1024); -// printByteBuffer(bb); - for (bb.position(0); bb.position() < bb.limit(); ) { - if ((bb.get() & 0xff) != 0) - throw new RuntimeException("uninitialized buffer, position = " - + bb.position()); + // Try power of two limits + for (int limit = 1; limit < MAX_BIN_LIMIT; limit *= 2) { + check(ByteBuffer.allocateDirect(limit - 1)); + check(ByteBuffer.allocateDirect(limit)); + check(ByteBuffer.allocateDirect(limit + 1)); + } + + // Try power of ten limits + for (int limit = 1; limit < MAX_DEC_LIMIT; limit *= 10) { + check(ByteBuffer.allocateDirect(limit - 1)); + check(ByteBuffer.allocateDirect(limit)); + check(ByteBuffer.allocateDirect(limit + 1)); + } + + // Try random sizes within power of two limits + for (int limit = 1; limit < MAX_BIN_LIMIT; limit *= 2) { + for (int t = 0; t < TRIES_PER_LIMIT; t++) { + check(ByteBuffer.allocateDirect(RND.nextInt(limit))); } } } - private static void printByteBuffer(ByteBuffer bb) { - System.out.print("byte ["); - for (bb.position(0); bb.position() < bb.limit(); ) - System.out.print(" " + Integer.toHexString(bb.get() & 0xff)); - System.out.println(" ]"); + private static void check(ByteBuffer bb) { + while (bb.hasRemaining()) { + if (bb.get() != 0) { + int mismatchPos = bb.position(); + System.out.print("byte ["); + for (bb.position(0); bb.position() < bb.limit(); ) { + System.out.print(" " + Integer.toHexString(bb.get() & 0xff)); + } + System.out.println(" ]"); + throw new RuntimeException("uninitialized buffer, position = " + mismatchPos); + } + } } } diff --git a/test/micro/org/openjdk/bench/java/nio/DirectByteBufferAlloc.java b/test/micro/org/openjdk/bench/java/nio/DirectByteBufferAlloc.java new file mode 100644 index 00000000000..8e82b9a4487 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/nio/DirectByteBufferAlloc.java @@ -0,0 +1,60 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +package org.openjdk.bench.java.nio; + + +import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) +@Fork(3) +public class DirectByteBufferAlloc { + + @Param({ + "128", // 128 bytes + "1024", // 1KB + "1048576", // 1 MB + "16777216" // 16MB + }) + public int bytes; + + @Benchmark + public ByteBuffer allocateDirectBuffer() { + return ByteBuffer.allocateDirect(bytes); + } +} From e18277b470a162b9668297e8e286c812c4b0b604 Mon Sep 17 00:00:00 2001 From: Radim Vansa Date: Thu, 12 Jun 2025 12:29:15 +0000 Subject: [PATCH 023/213] 8352075: Perf regression accessing fields Reviewed-by: coleenp, iklam, jsjolen --- .../share/classfile/classFileParser.cpp | 8 + .../share/classfile/classFileParser.hpp | 3 +- .../share/classfile/fieldLayoutBuilder.cpp | 4 +- src/hotspot/share/classfile/javaClasses.cpp | 7 + src/hotspot/share/oops/fieldInfo.cpp | 229 ++++++++++++++++-- src/hotspot/share/oops/fieldInfo.hpp | 35 ++- src/hotspot/share/oops/fieldInfo.inline.hpp | 34 ++- src/hotspot/share/oops/fieldStreams.hpp | 29 ++- .../share/oops/fieldStreams.inline.hpp | 37 ++- src/hotspot/share/oops/instanceKlass.cpp | 28 ++- src/hotspot/share/oops/instanceKlass.hpp | 4 + .../share/prims/jvmtiRedefineClasses.cpp | 7 + src/hotspot/share/runtime/globals.hpp | 4 + src/hotspot/share/utilities/packedTable.cpp | 113 +++++++++ src/hotspot/share/utilities/packedTable.hpp | 123 ++++++++++ src/hotspot/share/utilities/unsigned5.hpp | 11 +- .../gtest/utilities/test_packedTable.cpp | 158 ++++++++++++ .../FieldStream/LocalFieldLookupTest.java | 140 +++++++++++ 18 files changed, 904 insertions(+), 70 deletions(-) create mode 100644 src/hotspot/share/utilities/packedTable.cpp create mode 100644 src/hotspot/share/utilities/packedTable.hpp create mode 100644 test/hotspot/gtest/utilities/test_packedTable.cpp create mode 100644 test/hotspot/jtreg/runtime/FieldStream/LocalFieldLookupTest.java diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index bfb41f8384a..edec019bd70 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -3740,6 +3740,7 @@ void ClassFileParser::apply_parsed_class_metadata( _cp->set_pool_holder(this_klass); this_klass->set_constants(_cp); this_klass->set_fieldinfo_stream(_fieldinfo_stream); + this_klass->set_fieldinfo_search_table(_fieldinfo_search_table); this_klass->set_fields_status(_fields_status); this_klass->set_methods(_methods); this_klass->set_inner_classes(_inner_classes); @@ -3749,6 +3750,8 @@ void ClassFileParser::apply_parsed_class_metadata( this_klass->set_permitted_subclasses(_permitted_subclasses); this_klass->set_record_components(_record_components); + DEBUG_ONLY(FieldInfoStream::validate_search_table(_cp, _fieldinfo_stream, _fieldinfo_search_table)); + // Delay the setting of _local_interfaces and _transitive_interfaces until after // initialize_supers() in fill_instance_klass(). It is because the _local_interfaces could // be shared with _transitive_interfaces and _transitive_interfaces may be shared with @@ -5056,6 +5059,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, // note that is not safe to use the fields in the parser from this point on assert(nullptr == _cp, "invariant"); assert(nullptr == _fieldinfo_stream, "invariant"); + assert(nullptr == _fieldinfo_search_table, "invariant"); assert(nullptr == _fields_status, "invariant"); assert(nullptr == _methods, "invariant"); assert(nullptr == _inner_classes, "invariant"); @@ -5276,6 +5280,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, _super_klass(), _cp(nullptr), _fieldinfo_stream(nullptr), + _fieldinfo_search_table(nullptr), _fields_status(nullptr), _methods(nullptr), _inner_classes(nullptr), @@ -5352,6 +5357,7 @@ void ClassFileParser::clear_class_metadata() { // deallocated if classfile parsing returns an error. _cp = nullptr; _fieldinfo_stream = nullptr; + _fieldinfo_search_table = nullptr; _fields_status = nullptr; _methods = nullptr; _inner_classes = nullptr; @@ -5374,6 +5380,7 @@ ClassFileParser::~ClassFileParser() { if (_fieldinfo_stream != nullptr) { MetadataFactory::free_array(_loader_data, _fieldinfo_stream); } + MetadataFactory::free_array(_loader_data, _fieldinfo_search_table); if (_fields_status != nullptr) { MetadataFactory::free_array(_loader_data, _fields_status); @@ -5774,6 +5781,7 @@ void ClassFileParser::post_process_parsed_stream(const ClassFileStream* const st _fieldinfo_stream = FieldInfoStream::create_FieldInfoStream(_temp_field_info, _java_fields_count, injected_fields_count, loader_data(), CHECK); + _fieldinfo_search_table = FieldInfoStream::create_search_table(_cp, _fieldinfo_stream, _loader_data, CHECK); _fields_status = MetadataFactory::new_array(_loader_data, _temp_field_info->length(), FieldStatus(0), CHECK); diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp index 8f9f4ebea4d..707fbf6985f 100644 --- a/src/hotspot/share/classfile/classFileParser.hpp +++ b/src/hotspot/share/classfile/classFileParser.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -123,6 +123,7 @@ class ClassFileParser { const InstanceKlass* _super_klass; ConstantPool* _cp; Array* _fieldinfo_stream; + Array* _fieldinfo_search_table; Array* _fields_status; Array* _methods; Array* _inner_classes; diff --git a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp index b6007923907..03afe89f4f8 100644 --- a/src/hotspot/share/classfile/fieldLayoutBuilder.cpp +++ b/src/hotspot/share/classfile/fieldLayoutBuilder.cpp @@ -301,7 +301,7 @@ void FieldLayout::reconstruct_layout(const InstanceKlass* ik, bool& has_instance BasicType last_type; int last_offset = -1; while (ik != nullptr) { - for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) { + for (AllFieldStream fs(ik); !fs.done(); fs.next()) { BasicType type = Signature::basic_type(fs.signature()); // distinction between static and non-static fields is missing if (fs.access_flags().is_static()) continue; @@ -461,7 +461,7 @@ void FieldLayout::print(outputStream* output, bool is_static, const InstanceKlas bool found = false; const InstanceKlass* ik = super; while (!found && ik != nullptr) { - for (AllFieldStream fs(ik->fieldinfo_stream(), ik->constants()); !fs.done(); fs.next()) { + for (AllFieldStream fs(ik); !fs.done(); fs.next()) { if (fs.offset() == b->offset()) { output->print_cr(" @%d \"%s\" %s %d/%d %s", b->offset(), diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 8d32d73fb47..0e8467289ad 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -967,6 +967,13 @@ void java_lang_Class::fixup_mirror(Klass* k, TRAPS) { Array* new_fis = FieldInfoStream::create_FieldInfoStream(fields, java_fields, injected_fields, k->class_loader_data(), CHECK); ik->set_fieldinfo_stream(new_fis); MetadataFactory::free_array(k->class_loader_data(), old_stream); + + Array* old_table = ik->fieldinfo_search_table(); + Array* search_table = FieldInfoStream::create_search_table(ik->constants(), new_fis, k->class_loader_data(), CHECK); + ik->set_fieldinfo_search_table(search_table); + MetadataFactory::free_array(k->class_loader_data(), old_table); + + DEBUG_ONLY(FieldInfoStream::validate_search_table(ik->constants(), new_fis, search_table)); } } diff --git a/src/hotspot/share/oops/fieldInfo.cpp b/src/hotspot/share/oops/fieldInfo.cpp index 300b45277ad..d0825ba6df8 100644 --- a/src/hotspot/share/oops/fieldInfo.cpp +++ b/src/hotspot/share/oops/fieldInfo.cpp @@ -22,8 +22,11 @@ * */ +#include "memory/resourceArea.hpp" +#include "cds/cdsConfig.hpp" #include "oops/fieldInfo.inline.hpp" #include "runtime/atomic.hpp" +#include "utilities/packedTable.hpp" void FieldInfo::print(outputStream* os, ConstantPool* cp) { os->print_cr("index=%d name_index=%d name=%s signature_index=%d signature=%s offset=%d " @@ -37,8 +40,10 @@ void FieldInfo::print(outputStream* os, ConstantPool* cp) { field_flags().as_uint(), initializer_index(), generic_signature_index(), - _field_flags.is_injected() ? lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8(), - contended_group()); + _field_flags.is_generic() ? (_field_flags.is_injected() ? + lookup_symbol(generic_signature_index())->as_utf8() : cp->symbol_at(generic_signature_index())->as_utf8() + ) : "", + is_contended() ? contended_group() : 0); } void FieldInfo::print_from_growable_array(outputStream* os, GrowableArray* array, ConstantPool* cp) { @@ -62,13 +67,17 @@ Array* FieldInfoStream::create_FieldInfoStream(GrowableArray* fie StreamSizer s; StreamFieldSizer sizer(&s); + assert(fields->length() == java_fields + injected_fields, "must be"); + sizer.consumer()->accept_uint(java_fields); sizer.consumer()->accept_uint(injected_fields); for (int i = 0; i < fields->length(); i++) { FieldInfo* fi = fields->adr_at(i); sizer.map_field_info(*fi); } - int storage_size = sizer.consumer()->position() + 1; + // Originally there was an extra byte with 0 terminating the reading; + // now we check limits instead. + int storage_size = sizer.consumer()->position(); Array* const fis = MetadataFactory::new_array(loader_data, storage_size, CHECK_NULL); using StreamWriter = UNSIGNED5::Writer*, int, ArrayHelper*, int>>; @@ -79,15 +88,14 @@ Array* FieldInfoStream::create_FieldInfoStream(GrowableArray* fie writer.consumer()->accept_uint(java_fields); writer.consumer()->accept_uint(injected_fields); for (int i = 0; i < fields->length(); i++) { - FieldInfo* fi = fields->adr_at(i); - writer.map_field_info(*fi); + writer.map_field_info(fields->at(i)); } #ifdef ASSERT FieldInfoReader r(fis); - int jfc = r.next_uint(); + int jfc, ifc; + r.read_field_counts(&jfc, &ifc); assert(jfc == java_fields, "Must be"); - int ifc = r.next_uint(); assert(ifc == injected_fields, "Must be"); for (int i = 0; i < jfc + ifc; i++) { FieldInfo fi; @@ -113,30 +121,221 @@ Array* FieldInfoStream::create_FieldInfoStream(GrowableArray* fie return fis; } +int FieldInfoStream::compare_name_and_sig(const Symbol* n1, const Symbol* s1, const Symbol* n2, const Symbol* s2) { + int cmp = n1->fast_compare(n2); + return cmp != 0 ? cmp : s1->fast_compare(s2); +} + + +// We use both name and signature during the comparison; while JLS require unique +// names for fields, JVMS requires only unique name + signature combination. +struct field_pos { + Symbol* _name; + Symbol* _signature; + int _index; + int _position; +}; + +class FieldInfoSupplier: public PackedTableBuilder::Supplier { + const field_pos* _positions; + size_t _elements; + +public: + FieldInfoSupplier(const field_pos* positions, size_t elements): _positions(positions), _elements(elements) {} + + bool next(uint32_t* key, uint32_t* value) override { + if (_elements == 0) { + return false; + } + *key = _positions->_position; + *value = _positions->_index; + ++_positions; + --_elements; + return true; + } +}; + +Array* FieldInfoStream::create_search_table(ConstantPool* cp, const Array* fis, ClassLoaderData* loader_data, TRAPS) { + if (CDSConfig::is_dumping_dynamic_archive()) { + // We cannot use search table; in case of dynamic archives it should be sorted by "requested" addresses, + // but Symbol* addresses are coming from _constants, which has "buffered" addresses. + // For background, see new comments inside allocate_node_impl in symbolTable.cpp + return nullptr; + } + + FieldInfoReader r(fis); + int java_fields; + int injected_fields; + r.read_field_counts(&java_fields, &injected_fields); + assert(java_fields >= 0, "must be"); + if (java_fields == 0 || fis->length() == 0 || static_cast(java_fields) < BinarySearchThreshold) { + return nullptr; + } + + ResourceMark rm; + field_pos* positions = NEW_RESOURCE_ARRAY(field_pos, java_fields); + for (int i = 0; i < java_fields; ++i) { + assert(r.has_next(), "number of fields must match"); + + positions[i]._position = r.position(); + FieldInfo fi; + r.read_field_info(fi); + + positions[i]._name = fi.name(cp); + positions[i]._signature = fi.signature(cp); + positions[i]._index = i; + } + auto compare_pair = [](const void* v1, const void* v2) { + const field_pos* p1 = reinterpret_cast(v1); + const field_pos* p2 = reinterpret_cast(v2); + return compare_name_and_sig(p1->_name, p1->_signature, p2->_name, p2->_signature); + }; + qsort(positions, java_fields, sizeof(field_pos), compare_pair); + + PackedTableBuilder builder(fis->length() - 1, java_fields - 1); + Array* table = MetadataFactory::new_array(loader_data, java_fields * builder.element_bytes(), CHECK_NULL); + FieldInfoSupplier supplier(positions, java_fields); + builder.fill(table->data(), static_cast(table->length()), supplier); + return table; +} + GrowableArray* FieldInfoStream::create_FieldInfoArray(const Array* fis, int* java_fields_count, int* injected_fields_count) { - int length = FieldInfoStream::num_total_fields(fis); - GrowableArray* array = new GrowableArray(length); FieldInfoReader r(fis); - *java_fields_count = r.next_uint(); - *injected_fields_count = r.next_uint(); + r.read_field_counts(java_fields_count, injected_fields_count); + int length = *java_fields_count + *injected_fields_count; + + GrowableArray* array = new GrowableArray(length); while (r.has_next()) { FieldInfo fi; r.read_field_info(fi); array->append(fi); } assert(array->length() == length, "Must be"); - assert(array->length() == *java_fields_count + *injected_fields_count, "Must be"); return array; } void FieldInfoStream::print_from_fieldinfo_stream(Array* fis, outputStream* os, ConstantPool* cp) { - int length = FieldInfoStream::num_total_fields(fis); FieldInfoReader r(fis); - int java_field_count = r.next_uint(); - int injected_fields_count = r.next_uint(); + int java_fields_count; + int injected_fields_count; + r.read_field_counts(&java_fields_count, &injected_fields_count); while (r.has_next()) { FieldInfo fi; r.read_field_info(fi); fi.print(os, cp); } } + +class FieldInfoComparator: public PackedTableLookup::Comparator { + const FieldInfoReader* _reader; + ConstantPool* _cp; + const Symbol* _name; + const Symbol* _signature; + +public: + FieldInfoComparator(const FieldInfoReader* reader, ConstantPool* cp, const Symbol* name, const Symbol* signature): + _reader(reader), _cp(cp), _name(name), _signature(signature) {} + + int compare_to(uint32_t position) override { + FieldInfoReader r2(*_reader); + r2.set_position_and_next_index(position, -1); + u2 name_index, sig_index; + r2.read_name_and_signature(&name_index, &sig_index); + Symbol* mid_name = _cp->symbol_at(name_index); + Symbol* mid_sig = _cp->symbol_at(sig_index); + + return FieldInfoStream::compare_name_and_sig(_name, _signature, mid_name, mid_sig); + } + +#ifdef ASSERT + void reset(uint32_t position) override { + FieldInfoReader r2(*_reader); + r2.set_position_and_next_index(position, -1); + u2 name_index, signature_index; + r2.read_name_and_signature(&name_index, &signature_index); + _name = _cp->symbol_at(name_index); + _signature = _cp->symbol_at(signature_index); + } +#endif // ASSERT +}; + +#ifdef ASSERT +void FieldInfoStream::validate_search_table(ConstantPool* cp, const Array* fis, const Array* search_table) { + if (search_table == nullptr) { + return; + } + FieldInfoReader reader(fis); + int java_fields, injected_fields; + reader.read_field_counts(&java_fields, &injected_fields); + assert(java_fields > 0, "must be"); + + PackedTableLookup lookup(fis->length() - 1, java_fields - 1, search_table); + assert(lookup.element_bytes() * java_fields == static_cast(search_table->length()), "size does not match"); + + FieldInfoComparator comparator(&reader, cp, nullptr, nullptr); + // Check 1: assert that elements have the correct order based on the comparison function + lookup.validate_order(comparator); + + // Check 2: Iterate through the original stream (not just search_table) and try if lookup works as expected + reader.set_position_and_next_index(0, 0); + reader.read_field_counts(&java_fields, &injected_fields); + while (reader.has_next()) { + int field_start = reader.position(); + FieldInfo fi; + reader.read_field_info(fi); + if (fi.field_flags().is_injected()) { + // checking only java fields that precede injected ones + break; + } + + FieldInfoReader r2(fis); + int index = r2.search_table_lookup(search_table, fi.name(cp), fi.signature(cp), cp, java_fields); + assert(index == static_cast(fi.index()), "wrong index: %d != %u", index, fi.index()); + assert(index == r2.next_index(), "index should match"); + assert(field_start == r2.position(), "must find the same position"); + } +} +#endif // ASSERT + +void FieldInfoStream::print_search_table(outputStream* st, ConstantPool* cp, const Array* fis, const Array* search_table) { + if (search_table == nullptr) { + return; + } + FieldInfoReader reader(fis); + int java_fields, injected_fields; + reader.read_field_counts(&java_fields, &injected_fields); + assert(java_fields > 0, "must be"); + PackedTableLookup lookup(fis->length() - 1, java_fields - 1, search_table); + auto printer = [&] (size_t offset, uint32_t position, uint32_t index) { + reader.set_position_and_next_index(position, -1); + u2 name_index, sig_index; + reader.read_name_and_signature(&name_index, &sig_index); + Symbol* name = cp->symbol_at(name_index); + Symbol* sig = cp->symbol_at(sig_index); + st->print(" [%zu] #%d,#%d = ", offset, name_index, sig_index); + name->print_symbol_on(st); + st->print(":"); + sig->print_symbol_on(st); + st->print(" @ %p,%p", name, sig); + st->cr(); + }; + + lookup.iterate(printer); +} + +int FieldInfoReader::search_table_lookup(const Array* search_table, const Symbol* name, const Symbol* signature, ConstantPool* cp, int java_fields) { + assert(java_fields >= 0, "must be"); + if (java_fields == 0) { + return -1; + } + FieldInfoComparator comp(this, cp, name, signature); + PackedTableLookup lookup(_r.limit() - 1, java_fields - 1, search_table); + uint32_t position; + static_assert(sizeof(uint32_t) == sizeof(_next_index), "field size assert"); + if (lookup.search(comp, &position, reinterpret_cast(&_next_index))) { + _r.set_position(static_cast(position)); + return _next_index; + } else { + return -1; + } +} diff --git a/src/hotspot/share/oops/fieldInfo.hpp b/src/hotspot/share/oops/fieldInfo.hpp index 8740d539c8f..a98895da9cf 100644 --- a/src/hotspot/share/oops/fieldInfo.hpp +++ b/src/hotspot/share/oops/fieldInfo.hpp @@ -222,29 +222,28 @@ class Mapper { void map_field_info(const FieldInfo& fi); }; - // Gadget for decoding and reading the stream of field records. class FieldInfoReader { - friend class FieldInfoStream; - friend class ClassFileParser; - friend class FieldStreamBase; - friend class FieldInfo; - UNSIGNED5::Reader _r; int _next_index; - public: +public: FieldInfoReader(const Array* fi); - private: - uint32_t next_uint() { return _r.next_uint(); } +private: + inline uint32_t next_uint() { return _r.next_uint(); } void skip(int n) { int s = _r.try_skip(n); assert(s == n,""); } public: - int has_next() { return _r.has_next(); } - int position() { return _r.position(); } - int next_index() { return _next_index; } + void read_field_counts(int* java_fields, int* injected_fields); + int has_next() const { return _r.position() < _r.limit(); } + int position() const { return _r.position(); } + int next_index() const { return _next_index; } + void read_name_and_signature(u2* name_index, u2* signature_index); void read_field_info(FieldInfo& fi); + + int search_table_lookup(const Array* search_table, const Symbol* name, const Symbol* signature, ConstantPool* cp, int java_fields); + // skip a whole field record, both required and optional bits FieldInfoReader& skip_field_info(); @@ -271,6 +270,11 @@ class FieldInfoStream : AllStatic { friend class JavaFieldStream; friend class FieldStreamBase; friend class ClassFileParser; + friend class FieldInfoReader; + friend class FieldInfoComparator; + + private: + static int compare_name_and_sig(const Symbol* n1, const Symbol* s1, const Symbol* n2, const Symbol* s2); public: static int num_java_fields(const Array* fis); @@ -278,9 +282,14 @@ class FieldInfoStream : AllStatic { static int num_total_fields(const Array* fis); static Array* create_FieldInfoStream(GrowableArray* fields, int java_fields, int injected_fields, - ClassLoaderData* loader_data, TRAPS); + ClassLoaderData* loader_data, TRAPS); + static Array* create_search_table(ConstantPool* cp, const Array* fis, ClassLoaderData* loader_data, TRAPS); static GrowableArray* create_FieldInfoArray(const Array* fis, int* java_fields_count, int* injected_fields_count); static void print_from_fieldinfo_stream(Array* fis, outputStream* os, ConstantPool* cp); + + DEBUG_ONLY(static void validate_search_table(ConstantPool* cp, const Array* fis, const Array* search_table);) + + static void print_search_table(outputStream* st, ConstantPool* cp, const Array* fis, const Array* search_table); }; class FieldStatus { diff --git a/src/hotspot/share/oops/fieldInfo.inline.hpp b/src/hotspot/share/oops/fieldInfo.inline.hpp index d3d4d765081..842393729b2 100644 --- a/src/hotspot/share/oops/fieldInfo.inline.hpp +++ b/src/hotspot/share/oops/fieldInfo.inline.hpp @@ -56,16 +56,27 @@ inline Symbol* FieldInfo::lookup_symbol(int symbol_index) const { inline int FieldInfoStream::num_injected_java_fields(const Array* fis) { FieldInfoReader fir(fis); - fir.skip(1); - return fir.next_uint(); + int java_fields_count; + int injected_fields_count; + fir.read_field_counts(&java_fields_count, &injected_fields_count); + return injected_fields_count; } inline int FieldInfoStream::num_total_fields(const Array* fis) { FieldInfoReader fir(fis); - return fir.next_uint() + fir.next_uint(); + int java_fields_count; + int injected_fields_count; + fir.read_field_counts(&java_fields_count, &injected_fields_count); + return java_fields_count + injected_fields_count; } -inline int FieldInfoStream::num_java_fields(const Array* fis) { return FieldInfoReader(fis).next_uint(); } +inline int FieldInfoStream::num_java_fields(const Array* fis) { + FieldInfoReader fir(fis); + int java_fields_count; + int injected_fields_count; + fir.read_field_counts(&java_fields_count, &injected_fields_count); + return java_fields_count; +} template inline void Mapper::map_field_info(const FieldInfo& fi) { @@ -94,13 +105,22 @@ inline void Mapper::map_field_info(const FieldInfo& fi) { inline FieldInfoReader::FieldInfoReader(const Array* fi) - : _r(fi->data(), 0), + : _r(fi->data(), fi->length()), _next_index(0) { } +inline void FieldInfoReader::read_field_counts(int* java_fields, int* injected_fields) { + *java_fields = next_uint(); + *injected_fields = next_uint(); +} + +inline void FieldInfoReader::read_name_and_signature(u2* name_index, u2* signature_index) { + *name_index = checked_cast(next_uint()); + *signature_index = checked_cast(next_uint()); +} + inline void FieldInfoReader::read_field_info(FieldInfo& fi) { fi._index = _next_index++; - fi._name_index = checked_cast(next_uint()); - fi._signature_index = checked_cast(next_uint()); + read_name_and_signature(&fi._name_index, &fi._signature_index); fi._offset = next_uint(); fi._access_flags = AccessFlags(checked_cast(next_uint())); fi._field_flags = FieldInfo::FieldFlags(next_uint()); diff --git a/src/hotspot/share/oops/fieldStreams.hpp b/src/hotspot/share/oops/fieldStreams.hpp index a1c5d77eeb6..0ae828d73d9 100644 --- a/src/hotspot/share/oops/fieldStreams.hpp +++ b/src/hotspot/share/oops/fieldStreams.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,17 +56,23 @@ class FieldStreamBase : public StackObj { inline FieldStreamBase(const Array* fieldinfo_stream, ConstantPool* constants, int start, int limit); - inline FieldStreamBase(Array* fieldinfo_stream, ConstantPool* constants); + inline FieldStreamBase(const Array* fieldinfo_stream, ConstantPool* constants); - private: + private: void initialize() { - int java_fields_count = _reader.next_uint(); - int injected_fields_count = _reader.next_uint(); - assert( _limit <= java_fields_count + injected_fields_count, "Safety check"); + int java_fields_count; + int injected_fields_count; + _reader.read_field_counts(&java_fields_count, &injected_fields_count); + if (_limit < _index) { + _limit = java_fields_count + injected_fields_count; + } else { + assert( _limit <= java_fields_count + injected_fields_count, "Safety check"); + } if (_limit != 0) { _reader.read_field_info(_fi_buf); } } + public: inline FieldStreamBase(InstanceKlass* klass); @@ -138,8 +144,11 @@ class FieldStreamBase : public StackObj { // Iterate over only the Java fields class JavaFieldStream : public FieldStreamBase { + Array* _search_table; + public: - JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()) {} + JavaFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants(), 0, k->java_fields_count()), + _search_table(k->fieldinfo_search_table()) {} u2 name_index() const { assert(!field()->field_flags().is_injected(), "regular only"); @@ -149,7 +158,6 @@ class JavaFieldStream : public FieldStreamBase { u2 signature_index() const { assert(!field()->field_flags().is_injected(), "regular only"); return field()->signature_index(); - return -1; } u2 generic_signature_index() const { @@ -164,6 +172,10 @@ class JavaFieldStream : public FieldStreamBase { assert(!field()->field_flags().is_injected(), "regular only"); return field()->initializer_index(); } + + // Performs either a linear search or binary search through the stream + // looking for a matching name/signature combo + bool lookup(const Symbol* name, const Symbol* signature); }; @@ -176,7 +188,6 @@ class InternalFieldStream : public FieldStreamBase { class AllFieldStream : public FieldStreamBase { public: - AllFieldStream(Array* fieldinfo, ConstantPool* constants): FieldStreamBase(fieldinfo, constants) {} AllFieldStream(const InstanceKlass* k): FieldStreamBase(k->fieldinfo_stream(), k->constants()) {} }; diff --git a/src/hotspot/share/oops/fieldStreams.inline.hpp b/src/hotspot/share/oops/fieldStreams.inline.hpp index 776bcd1671c..51faf88c678 100644 --- a/src/hotspot/share/oops/fieldStreams.inline.hpp +++ b/src/hotspot/share/oops/fieldStreams.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,22 +33,18 @@ FieldStreamBase::FieldStreamBase(const Array* fieldinfo_stream, ConstantPool* constants, int start, int limit) : _fieldinfo_stream(fieldinfo_stream), _reader(FieldInfoReader(_fieldinfo_stream)), - _constants(constantPoolHandle(Thread::current(), constants)), _index(start) { - _index = start; - if (limit < start) { - _limit = FieldInfoStream::num_total_fields(_fieldinfo_stream); - } else { - _limit = limit; - } + _constants(constantPoolHandle(Thread::current(), constants)), + _index(start), + _limit(limit) { initialize(); } -FieldStreamBase::FieldStreamBase(Array* fieldinfo_stream, ConstantPool* constants) : +FieldStreamBase::FieldStreamBase(const Array* fieldinfo_stream, ConstantPool* constants) : _fieldinfo_stream(fieldinfo_stream), _reader(FieldInfoReader(_fieldinfo_stream)), _constants(constantPoolHandle(Thread::current(), constants)), _index(0), - _limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) { + _limit(-1) { initialize(); } @@ -57,9 +53,28 @@ FieldStreamBase::FieldStreamBase(InstanceKlass* klass) : _reader(FieldInfoReader(_fieldinfo_stream)), _constants(constantPoolHandle(Thread::current(), klass->constants())), _index(0), - _limit(FieldInfoStream::num_total_fields(_fieldinfo_stream)) { + _limit(-1) { assert(klass == field_holder(), ""); initialize(); } +inline bool JavaFieldStream::lookup(const Symbol* name, const Symbol* signature) { + if (_search_table != nullptr) { + int index = _reader.search_table_lookup(_search_table, name, signature, _constants(), _limit); + if (index >= 0) { + assert(index < _limit, "must be"); + _index = index; + _reader.read_field_info(_fi_buf); + return true; + } + } else { + for (; !done(); next()) { + if (this->name() == name && this->signature() == signature) { + return true; + } + } + } + return false; +} + #endif // SHARE_OOPS_FIELDSTREAMS_INLINE_HPP diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 32d7943e1e8..1bb6b3bdf98 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -686,6 +686,11 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { } set_fieldinfo_stream(nullptr); + if (fieldinfo_search_table() != nullptr && !fieldinfo_search_table()->is_shared()) { + MetadataFactory::free_array(loader_data, fieldinfo_search_table()); + } + set_fieldinfo_search_table(nullptr); + if (fields_status() != nullptr && !fields_status()->is_shared()) { MetadataFactory::free_array(loader_data, fields_status()); } @@ -1786,13 +1791,12 @@ FieldInfo InstanceKlass::field(int index) const { } bool InstanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const { - for (JavaFieldStream fs(this); !fs.done(); fs.next()) { - Symbol* f_name = fs.name(); - Symbol* f_sig = fs.signature(); - if (f_name == name && f_sig == sig) { - fd->reinitialize(const_cast(this), fs.to_FieldInfo()); - return true; - } + JavaFieldStream fs(this); + if (fs.lookup(name, sig)) { + assert(fs.name() == name, "name must match"); + assert(fs.signature() == sig, "signature must match"); + fd->reinitialize(const_cast(this), fs.to_FieldInfo()); + return true; } return false; } @@ -2610,6 +2614,7 @@ void InstanceKlass::metaspace_pointers_do(MetaspaceClosure* it) { } it->push(&_fieldinfo_stream); + it->push(&_fieldinfo_search_table); // _fields_status might be written into by Rewriter::scan_method() -> fd.set_has_initialized_final_update() it->push(&_fields_status, MetaspaceClosure::_writable); @@ -2710,6 +2715,8 @@ void InstanceKlass::remove_unshareable_info() { DEBUG_ONLY(_shared_class_load_count = 0); remove_unshareable_flags(); + + DEBUG_ONLY(FieldInfoStream::validate_search_table(_constants, _fieldinfo_stream, _fieldinfo_search_table)); } void InstanceKlass::remove_unshareable_flags() { @@ -2816,6 +2823,8 @@ void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handl if (DiagnoseSyncOnValueBasedClasses && has_value_based_class_annotation() && !is_value_based()) { set_is_value_based(); } + + DEBUG_ONLY(FieldInfoStream::validate_search_table(_constants, _fieldinfo_stream, _fieldinfo_search_table)); } // Check if a class or any of its supertypes has a version older than 50. @@ -3760,6 +3769,11 @@ void InstanceKlass::print_on(outputStream* st) const { map++; } st->cr(); + + if (fieldinfo_search_table() != nullptr) { + st->print_cr(BULLET"---- field info search table:"); + FieldInfoStream::print_search_table(st, _constants, _fieldinfo_stream, _fieldinfo_search_table); + } } void InstanceKlass::print_value_on(outputStream* st) const { diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 078c5b81841..55ab0996a4a 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -276,6 +276,7 @@ class InstanceKlass: public Klass { // Fields information is stored in an UNSIGNED5 encoded stream (see fieldInfo.hpp) Array* _fieldinfo_stream; + Array* _fieldinfo_search_table; Array* _fields_status; // embedded Java vtable follows here @@ -398,6 +399,9 @@ class InstanceKlass: public Klass { Array* fieldinfo_stream() const { return _fieldinfo_stream; } void set_fieldinfo_stream(Array* fis) { _fieldinfo_stream = fis; } + Array* fieldinfo_search_table() const { return _fieldinfo_search_table; } + void set_fieldinfo_search_table(Array* table) { _fieldinfo_search_table = table; } + Array* fields_status() const {return _fields_status; } void set_fields_status(Array* array) { _fields_status = array; } diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index af9d973d2f1..305af6df9be 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -3550,6 +3550,13 @@ void VM_RedefineClasses::set_new_constant_pool( Array* new_fis = FieldInfoStream::create_FieldInfoStream(fields, java_fields, injected_fields, scratch_class->class_loader_data(), CHECK); scratch_class->set_fieldinfo_stream(new_fis); MetadataFactory::free_array(scratch_class->class_loader_data(), old_stream); + + Array* old_table = scratch_class->fieldinfo_search_table(); + Array* search_table = FieldInfoStream::create_search_table(scratch_class->constants(), new_fis, scratch_class->class_loader_data(), CHECK); + scratch_class->set_fieldinfo_search_table(search_table); + MetadataFactory::free_array(scratch_class->class_loader_data(), old_table); + + DEBUG_ONLY(FieldInfoStream::validate_search_table(scratch_class->constants(), new_fis, search_table)); } // Update constant pool indices in the inner classes info to use diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 290ce0d3cba..75736d0dc7d 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -2005,6 +2005,10 @@ const int ObjectAlignmentInBytes = 8; product(bool, UseThreadsLockThrottleLock, true, DIAGNOSTIC, \ "Use an extra lock during Thread start and exit to alleviate" \ "contention on Threads_lock.") \ + \ + develop(uint, BinarySearchThreshold, 16, \ + "Minimal number of elements in a sorted collection to prefer" \ + "binary search over simple linear search." ) \ // end of RUNTIME_FLAGS diff --git a/src/hotspot/share/utilities/packedTable.cpp b/src/hotspot/share/utilities/packedTable.cpp new file mode 100644 index 00000000000..134cd2cd751 --- /dev/null +++ b/src/hotspot/share/utilities/packedTable.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include + +#include "utilities/align.hpp" +#include "utilities/count_leading_zeros.hpp" +#include "utilities/packedTable.hpp" + +// The thresholds are inclusive, and in practice the limits are rounded +// to the nearest power-of-two - 1. +// Based on the max_key and max_value we figure out the number of bits required to store +// key and value; imagine that only as bits (not aligned to byte boundary... yet). +// Then we concatenate the bits for key and value, and 'add' 1-7 padding zeroes +// (high-order bits) to align on bytes. +// In the end we have each element in the table consuming 1-8 bytes (case with 0 bits for key +// is ruled out). +PackedTableBase::PackedTableBase(uint32_t max_key, uint32_t max_value) { + unsigned int key_bits = max_key == 0 ? 0 : 32 - count_leading_zeros(max_key); + unsigned int value_bits = max_value == 0 ? 0 : 32 - count_leading_zeros(max_value); + _element_bytes = align_up(key_bits + value_bits, 8) / 8; + // shifting left by 32 is undefined behaviour, and in practice returns 1 + _key_mask = key_bits >= 32 ? -1 : (1U << key_bits) - 1; + _value_shift = key_bits; + _value_mask = value_bits >= 32 ? -1 : (1U << value_bits) - 1; + guarantee(_element_bytes > 0, "wouldn't work"); + assert(_element_bytes <= sizeof(uint64_t), "shouldn't happen"); +} + +// Note: we require the supplier to provide the elements in the final order as we can't easily sort +// within this method - qsort() accepts only pure function as comparator. +void PackedTableBuilder::fill(u1* table, size_t table_length, Supplier &supplier) const { + uint32_t key, value; + size_t offset = 0; + for (; offset <= table_length && supplier.next(&key, &value); offset += _element_bytes) { + assert((key & ~_key_mask) == 0, "key out of bounds"); + assert((value & ~_value_mask) == 0, "value out of bounds: %x vs. %x (%x)", value, _value_mask, ~_value_mask); + uint64_t element = static_cast(key) | (static_cast(value) << _value_shift); + for (unsigned int i = 0; i < _element_bytes; ++i) { + table[offset + i] = static_cast(0xFF & element); + element >>= 8; + } + } + + assert(offset == table_length, "Did not fill whole array"); + assert(!supplier.next(&key, &value), "Supplier has more elements"); +} + +uint64_t PackedTableLookup::read_element(size_t offset) const { + uint64_t element = 0; + for (unsigned int i = 0; i < _element_bytes; ++i) { + element |= static_cast(_table[offset + i]) << (8 * i); + } + assert((element & ~((uint64_t) _key_mask | ((uint64_t) _value_mask << _value_shift))) == 0, "read too much"); + return element; +} + +bool PackedTableLookup::search(Comparator& comparator, uint32_t* found_key, uint32_t* found_value) const { + unsigned int low = 0, high = checked_cast(_table_length / _element_bytes); + assert(low < high, "must be"); + while (low < high) { + unsigned int mid = low + (high - low) / 2; + assert(mid >= low && mid < high, "integer overflow?"); + uint64_t element = read_element(_element_bytes * mid); + // Ignoring high 32 bits in element on purpose + uint32_t key = static_cast(element) & _key_mask; + int cmp = comparator.compare_to(key); + if (cmp == 0) { + *found_key = key; + // Since __builtin_memcpy in read_element does not copy bits outside the element + // anything above _value_mask << _value_shift should be zero. + *found_value = checked_cast(element >> _value_shift) & _value_mask; + return true; + } else if (cmp < 0) { + high = mid; + } else { + low = mid + 1; + } + } + return false; +} + +#ifdef ASSERT +void PackedTableLookup::validate_order(Comparator &comparator) const { + auto validator = [&] (size_t offset, uint32_t key, uint32_t value) { + if (offset != 0) { + assert(comparator.compare_to(key) < 0, "not sorted"); + } + comparator.reset(key); + }; + iterate(validator); +} +#endif diff --git a/src/hotspot/share/utilities/packedTable.hpp b/src/hotspot/share/utilities/packedTable.hpp new file mode 100644 index 00000000000..ed08a2b4c21 --- /dev/null +++ b/src/hotspot/share/utilities/packedTable.hpp @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "oops/array.hpp" +#include "utilities/globalDefinitions.hpp" + +// Base for space-optimized structure supporting binary search. Each element +// consists of up to 32-bit key, and up to 32-bit value; these are packed +// into a bit-record with 1-byte alignment. +// The keys are ordered according to a custom comparator. +class PackedTableBase { +protected: + unsigned int _element_bytes; + uint32_t _key_mask; + unsigned int _value_shift; + uint32_t _value_mask; + +public: + PackedTableBase(uint32_t max_key, uint32_t max_value); + + // Returns number of bytes each element will occupy. + inline unsigned int element_bytes(void) const { return _element_bytes; } +}; + +// Helper class for constructing a packed table in the provided array. +class PackedTableBuilder: public PackedTableBase { +public: + class Supplier { + public: + // Returns elements with already ordered keys. + // This function should return true when the key and value was set, + // and false when there's no more elements. + // Packed table does NOT support duplicate keys. + virtual bool next(uint32_t* key, uint32_t* value) = 0; + }; + + // The thresholds are inclusive, and in practice the limits are rounded + // to the nearest power-of-two - 1. + // See PackedTableBase constructor for details. + PackedTableBuilder(uint32_t max_key, uint32_t max_value): PackedTableBase(max_key, max_value) {} + + // Constructs a packed table in the provided array, filling it with elements + // from the supplier. Note that no comparator is requied by this method - + // the supplier must return elements with already ordered keys. + // The table_length (in bytes) should match number of elements provided + // by the supplier (when Supplier::next() returns false the whole array should + // be filled). + void fill(u1* table, size_t table_length, Supplier &supplier) const; +}; + +// Helper class for lookup in a packed table. +class PackedTableLookup: public PackedTableBase { + const u1* const _table; + const size_t _table_length; + + uint64_t read_element(size_t offset) const; + +public: + + // The comparator implementation does not have to store a key (uint32_t); + // the idea is that key can point into a different structure that hosts data + // suitable for the actual comparison. That's why PackedTableLookup::search(...) + // returns the key it found as well as the value. + class Comparator { + public: + // Returns negative/0/positive if the target referred to by this comparator + // is lower/equal/higher than the target referred to by the key. + virtual int compare_to(uint32_t key) = 0; + // Changes the target this comparator refers to. + DEBUG_ONLY(virtual void reset(uint32_t key) = 0); + }; + + // The thresholds are inclusive, and in practice the limits are rounded + // to the nearest power-of-two - 1. + // See PackedTableBase constructor for details. + PackedTableLookup(uint32_t max_key, uint32_t max_value, const u1 *table, size_t table_length): + PackedTableBase(max_key, max_value), _table(table), _table_length(table_length) {} + + PackedTableLookup(uint32_t max_key, uint32_t max_value, const Array *table): + PackedTableLookup(max_key, max_value, table->data(), static_cast(table->length())) {} + + // Performs a binary search in the packed table, looking for an element with key + // referring to a target equal according to the comparator. + // When the element is found, found_key and found_value are updated from the element + // and the function returns true. + // When the element is not found, found_key and found_value are not changed and + // the function returns false. + bool search(Comparator& comparator, uint32_t* found_key, uint32_t* found_value) const; + + // Asserts that elements in the packed table follow the order defined by the comparator. + DEBUG_ONLY(void validate_order(Comparator &comparator) const); + + template + void iterate(Function func) const { + for (size_t offset = 0; offset < _table_length; offset += _element_bytes) { + uint64_t element = read_element(offset); + uint32_t key = static_cast(element) & _key_mask; + uint32_t value = checked_cast(element >> _value_shift) & _value_mask; + func(offset, key, value); + } + } +}; diff --git a/src/hotspot/share/utilities/unsigned5.hpp b/src/hotspot/share/utilities/unsigned5.hpp index 7f74d6e8498..8e3724a0012 100644 --- a/src/hotspot/share/utilities/unsigned5.hpp +++ b/src/hotspot/share/utilities/unsigned5.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -261,7 +261,7 @@ class UNSIGNED5 : AllStatic { ARR _array; OFF _limit; OFF _position; - int next_length() { + int next_length() const { return UNSIGNED5::check_length(_array, _position, _limit, GET()); } public: @@ -270,7 +270,7 @@ class UNSIGNED5 : AllStatic { uint32_t next_uint() { return UNSIGNED5::read_uint(_array, _position, _limit, GET()); } - bool has_next() { + bool has_next() const { return next_length() != 0; } // tries to skip count logical entries; returns actual number skipped @@ -284,8 +284,9 @@ class UNSIGNED5 : AllStatic { return actual; } ARR array() { return _array; } - OFF limit() { return _limit; } - OFF position() { return _position; } + OFF limit() const { return _limit; } + OFF position() const { return _position; } + void set_limit(OFF limit) { _limit = limit; } void set_position(OFF position) { _position = position; } // For debugging, even in product builds (see debug.cpp). diff --git a/test/hotspot/gtest/utilities/test_packedTable.cpp b/test/hotspot/gtest/utilities/test_packedTable.cpp new file mode 100644 index 00000000000..2adf8a1f08d --- /dev/null +++ b/test/hotspot/gtest/utilities/test_packedTable.cpp @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include "utilities/packedTable.hpp" +#include "unittest.hpp" + +class Supplier: public PackedTableBuilder::Supplier { + uint32_t* _keys; + uint32_t* _values; + size_t _num_keys; + +public: + Supplier(uint32_t* keys, uint32_t* values, size_t num_keys): + _keys(keys), _values(values), _num_keys(num_keys) {} + + bool next(uint32_t* key, uint32_t* value) override { + if (_num_keys == 0) { + return false; + } + *key = *_keys; + ++_keys; + if (_values != nullptr) { + *value = *_values; + ++_values; + } else { + *value = 0; + } + --_num_keys; + return true; + } +}; + +class Comparator: public PackedTableLookup::Comparator { + uint32_t _current; + +public: + int compare_to(uint32_t key) override { + return _current < key ? -1 : (_current > key ? 1 : 0); + } + + void reset(uint32_t key) DEBUG_ONLY(override) { + _current = key; + } +}; + +static void test(uint32_t max_key, uint32_t max_value, unsigned int length) { + if (length > max_key + 1) { + // can't generate more keys, as keys must be unique + return; + } + PackedTableBuilder builder(max_key, max_value); + size_t table_length = length * builder.element_bytes(); + u1* table = new u1[table_length]; + + uint32_t* keys = new uint32_t[length]; + uint32_t* values = max_value != 0 ? new uint32_t[length] : nullptr; + for (unsigned int i = 0; i < length; ++i) { + keys[i] = i; + if (values != nullptr) { + values[i] = i % max_value; + } + } + Supplier sup(keys, values, length); + builder.fill(table, table_length, sup); + + Comparator comparator; + PackedTableLookup lookup(max_key, max_value, table, table_length); +#ifdef ASSERT + lookup.validate_order(comparator); +#endif + + for (unsigned int i = 0; i < length; ++i) { + uint32_t key, value; + comparator.reset(keys[i]); + EXPECT_TRUE(lookup.search(comparator, &key, &value)); + EXPECT_EQ(key, keys[i]); + if (values != nullptr) { + EXPECT_EQ(value, values[i]); + } else { + EXPECT_EQ(value, 0U); + } + } + + delete[] keys; + delete[] values; +} + +static void test_with_bits(uint32_t max_key, uint32_t max_value) { + // Some small sizes + for (unsigned int i = 0; i <= 100; ++i) { + test(max_key, max_value, i); + } + test(max_key, max_value, 10000); +} + +TEST(PackedTableLookup, lookup) { + for (int key_bits = 1; key_bits <= 32; ++key_bits) { + for (int value_bits = 0; value_bits <= 32; ++value_bits) { + test_with_bits(static_cast((1ULL << key_bits) - 1), + static_cast((1ULL << value_bits) - 1)); + } + } +} + +TEST(PackedTableBase, element_bytes) { + { + PackedTableBuilder builder(1, 0); + EXPECT_EQ(builder.element_bytes(), 1U); + } + { + PackedTableBuilder builder(15, 15); + EXPECT_EQ(builder.element_bytes(), 1U); + } + { + PackedTableBuilder builder(15, 16); + EXPECT_EQ(builder.element_bytes(), 2U); + } + { + PackedTableBuilder builder(31, 7); + EXPECT_EQ(builder.element_bytes(), 1U); + } + { + PackedTableBuilder builder(32, 7); + EXPECT_EQ(builder.element_bytes(), 2U); + } + { + PackedTableBuilder builder(-1, 0); + EXPECT_EQ(builder.element_bytes(), 4U); + } + { + PackedTableBuilder builder(-1, 1); + EXPECT_EQ(builder.element_bytes(), 5U); + } + { + PackedTableBuilder builder(-1, -1); + EXPECT_EQ(builder.element_bytes(), 8U); + } +} diff --git a/test/hotspot/jtreg/runtime/FieldStream/LocalFieldLookupTest.java b/test/hotspot/jtreg/runtime/FieldStream/LocalFieldLookupTest.java new file mode 100644 index 00000000000..bebef5acd0c --- /dev/null +++ b/test/hotspot/jtreg/runtime/FieldStream/LocalFieldLookupTest.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES; +import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS; +import static org.objectweb.asm.Opcodes.*; + +/* + * @test id=defaults + * @bug 8352075 + * @library /test/lib + * @library /testlibrary/asm + * @run main/othervm LocalFieldLookupTest + */ +/* + * @test id=custom-threshold + * @bug 8352075 + * @library /test/lib + * @library /testlibrary/asm + * @requires vm.debug == true + * @run main/othervm LocalFieldLookupTest + * @run main/othervm -XX:BinarySearchThreshold=0 LocalFieldLookupTest + * @run main/othervm -XX:BinarySearchThreshold=1 LocalFieldLookupTest + * @run main/othervm -XX:BinarySearchThreshold=15 LocalFieldLookupTest + * @run main/othervm -XX:BinarySearchThreshold=100000 LocalFieldLookupTest + */ +public class LocalFieldLookupTest { + private static final String TEST_CLASS_NAME = "Test"; + private static final int MAX_FIELDS_IN_METHOD = 10000; + + public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException { + // Test small classes, covering the tested thresholds + for (int i = 0; i <= 33; ++i) { + makeClass(i).newInstance(); + } + // Test classes around 256 fields (index encoding 1/2 bytes) to check off-by-one errors + for (int i = 254; i <= 259; ++i) { + makeClass(255).newInstance(); + } + // We would like to test #fields that create have the stream about 65536 bytes long; + // this value is not exposed, though, so these are rather experimentally found values, + // hence fragile. Moreover, since the stream length is incremented by about 8 bytes + // for each field we cannot test for off-by-one errors reliably. + for (int i = 8433; i <= 8437; ++i) { + makeClass(i).newInstance(); + } + // The largest class we can create - this one has 65533 entries in the constant pool + makeClass(26205).newInstance(); + } + + public static Class makeClass(int fields) throws ClassNotFoundException { + ClassWriter writer = new ClassWriter(COMPUTE_MAXS | COMPUTE_FRAMES); + writer.visit(49, Opcodes.ACC_PUBLIC + Opcodes.ACC_SUPER, TEST_CLASS_NAME,null, "java/lang/Object", null); + + for (int i = 0; i < fields; i += 2) { + writer.visitField(ACC_PUBLIC, "f" + i, "I", null, null); + // Let's use duplicate names to confirm search takes signatures into account + if (i + 1 < fields) { + writer.visitField(ACC_PUBLIC, "f" + i, "J", null, null); + } + } + // We initialize fields in multiple methods to avoid running into bytecode limit per method + MethodVisitor fi = null; + for (int i = 0; i < fields; i+= 2) { + if (fi == null) { + fi = writer.visitMethod(ACC_PRIVATE, "init" + i, "()V", null, null); + fi.visitCode(); + } + fi.visitVarInsn(Opcodes.ALOAD, 0); + fi.visitInsn(Opcodes.ICONST_2); + fi.visitFieldInsn(PUTFIELD, TEST_CLASS_NAME, "f" + i, "I"); + if (i + 1 < fields) { + fi.visitVarInsn(Opcodes.ALOAD, 0); + fi.visitInsn(Opcodes.LCONST_1); + fi.visitFieldInsn(PUTFIELD, TEST_CLASS_NAME, "f" + i, "J"); + } + if (i % MAX_FIELDS_IN_METHOD == MAX_FIELDS_IN_METHOD - 2) { + fi.visitInsn(Opcodes.RETURN); + fi.visitMaxs(0, 0); + fi.visitEnd(); + fi = null; + } + } + if (fi != null) { + fi.visitInsn(Opcodes.RETURN); + fi.visitMaxs(0, 0); + fi.visitEnd(); + } + { + MethodVisitor mv = writer.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + for (int i = 0; i < fields; i += MAX_FIELDS_IN_METHOD) { + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, TEST_CLASS_NAME, "init" + i, "()V", false); + } + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + } + writer.visitEnd(); + + byte[] bytecode = writer.toByteArray(); + ClassLoader cl = new ClassLoader() { + @Override + protected Class findClass(String name) throws ClassNotFoundException { + if (!TEST_CLASS_NAME.equals(name)) { + throw new ClassNotFoundException(); + } + return defineClass(TEST_CLASS_NAME, bytecode, 0, bytecode.length); + } + }; + return cl.loadClass(TEST_CLASS_NAME); + } +} From b85fe02be5966b72ea1a92bfb3faf088d310219a Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 14:12:14 +0000 Subject: [PATCH 024/213] 8358600: Template-Framework Library: Template for TestFramework test class Reviewed-by: chagedorn, mhaessig --- .../library/TestFrameworkClass.java | 119 +++++++++++++ .../examples/TestWithTestFrameworkClass.java | 163 ++++++++++++++++++ 2 files changed, 282 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java create mode 100644 test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestWithTestFrameworkClass.java diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java new file mode 100644 index 00000000000..5194b75af43 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/TestFrameworkClass.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.lib.template_framework.library; + +import java.util.List; +import java.util.Set; + +import compiler.lib.ir_framework.TestFramework; +import compiler.lib.compile_framework.CompileFramework; +import compiler.lib.template_framework.Template; +import compiler.lib.template_framework.TemplateToken; +import static compiler.lib.template_framework.Template.body; +import static compiler.lib.template_framework.Template.let; + +/** + * This class provides a {@link #render} method that can be used to simplify generating + * source code when using the {@link TestFramework} (also known as IR Framework) to run + * a list of tests. + * + *

+ * The idea is that the user only has to generate the code for the individual tests, + * and can then pass the corresponding list of {@link TemplateToken}s to this + * provided {@link #render} method which generates the surrounding class and the main + * method that invokes the {@link TestFramework}, so that all the generated tests + * are run. + */ +public final class TestFrameworkClass { + + // Ensure there can be no instance, and we do not have to document the constructor. + private TestFrameworkClass() {} + + /** + * This method renders a list of {@code testTemplateTokens} into the body of a class + * and generates a {@code main} method which launches the {@link TestFramework} + * to run the generated tests. + * + *

+ * The generated {@code main} method is to be invoked with a {@code vmFlags} argument, + * which must be a {@link String[]}, specifying the VM flags for the Test VM, in which + * the tests will be run. Thus, one can generate the test class once, and invoke its + * {@code main} method multiple times, each time with a different set of VM flags. + * + *

+ * The internal {@link Template} sets the {@link Hooks#CLASS_HOOK} for the scope of + * all test methods. + * + * @param packageName The package name of the test class. + * @param className The name of the test class. + * @param imports A set of imports. + * @param classpath The classpath from {@link CompileFramework#getEscapedClassPathOfCompiledClasses}, + * so that the Test VM has access to the class files that are compiled from the + * generated source code. + * @param testTemplateTokens The list of tests to be generated into the test class. + * Every test must be annotated with {@code @Test}, so that + * the {@link TestFramework} can later find and run them. + * @return The generated source code of the test class as a {@link String}. + */ + public static String render(final String packageName, + final String className, + final Set imports, + final String classpath, + final List testTemplateTokens) { + var template = Template.make(() -> body( + let("packageName", packageName), + let("className", className), + let("classpath", classpath), + """ + package #packageName; + // --- IMPORTS start --- + import compiler.lib.ir_framework.*; + """, + imports.stream().map(i -> "import " + i + ";\n").toList(), + """ + // --- IMPORTS end --- + public class #className { + // --- CLASS_HOOK insertions start --- + """, + Hooks.CLASS_HOOK.anchor( + """ + // --- CLASS_HOOK insertions end --- + public static void main(String[] vmFlags) { + TestFramework framework = new TestFramework(#className.class); + framework.addFlags("-classpath", "#classpath"); + framework.addFlags(vmFlags); + framework.start(); + } + // --- LIST OF TESTS start --- + """, + testTemplateTokens + ), + """ + // --- LIST OF TESTS end --- + } + """ + )); + return template.render(); + } +} diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestWithTestFrameworkClass.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestWithTestFrameworkClass.java new file mode 100644 index 00000000000..813f2976ef2 --- /dev/null +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestWithTestFrameworkClass.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test TestFrameworkClass.TEMPLATE which allows generating many tests and running them with the IR TestFramework. + * @modules java.base/jdk.internal.misc + * @library /test/lib / + * @compile ../../../compiler/lib/ir_framework/TestFramework.java + * @compile ../../../compiler/lib/generators/Generators.java + * @compile ../../../compiler/lib/verify/Verify.java + * @run driver template_framework.examples.TestWithTestFrameworkClass + */ + +package template_framework.examples; + +import java.util.List; +import java.util.Set; + +import compiler.lib.compile_framework.CompileFramework; + +import compiler.lib.generators.Generators; + +import compiler.lib.template_framework.Template; +import compiler.lib.template_framework.TemplateToken; +import static compiler.lib.template_framework.Template.body; +import static compiler.lib.template_framework.Template.let; + +import compiler.lib.template_framework.library.Hooks; +import compiler.lib.template_framework.library.TestFrameworkClass; + +/** + * This is a basic IR verification test, in combination with Generators for random input generation + * and Verify for output verification. + *

+ * The "@compile" command for JTREG is required so that the frameworks used in the Template code + * are compiled and available for the Test-VM. + *

+ * Additionally, we must set the classpath for the Test VM, so that it has access to all compiled + * classes (see {@link CompileFramework#getEscapedClassPathOfCompiledClasses}). + */ +public class TestWithTestFrameworkClass { + + public static void main(String[] args) { + // Create a new CompileFramework instance. + CompileFramework comp = new CompileFramework(); + + // Add a java source file. + comp.addJavaSourceCode("p.xyz.InnerTest", generate(comp)); + + // Compile the source file. + comp.compile(); + + // p.xyz.InnterTest.main(new String[] {}); + comp.invoke("p.xyz.InnerTest", "main", new Object[] {new String[] {}}); + + // We can also pass VM flags for the Test VM. + // p.xyz.InnterTest.main(new String[] {"-Xbatch"}); + comp.invoke("p.xyz.InnerTest", "main", new Object[] {new String[] {"-Xbatch"}}); + } + + // Generate a source Java file as String + public static String generate(CompileFramework comp) { + // A simple template that adds a comment. + var commentTemplate = Template.make(() -> body( + """ + // Comment inserted from test method to class hook. + """ + )); + + // We define a Test-Template: + // - static fields for inputs: INPUT_A and INPUT_B + // - Data generated with Generators and hashtag replacement #con1. + // - GOLD value precomputed with dedicated call to test. + // - This ensures that the GOLD value is computed in the interpreter + // most likely, since the test method is not yet compiled. + // This allows us later to compare to the results of the compiled + // code. + // The input data is cloned, so that the original INPUT_A is never + // modified and can serve as identical input in later calls to test. + // - In the Setup method, we clone the input data, since the input data + // could be modified inside the test method. + // - The test method makes use of hashtag replacements (#con2 and #op). + // - The Check method verifies the results of the test method with the + // GOLD value. + var testTemplate = Template.make("op", (String op) -> body( + let("size", Generators.G.safeRestrict(Generators.G.ints(), 10_000, 20_000).next()), + let("con1", Generators.G.ints().next()), + let("con2", Generators.G.safeRestrict(Generators.G.ints(), 1, Integer.MAX_VALUE).next()), + """ + // --- $test start --- + // $test with size=#size and op=#op + private static int[] $INPUT_A = new int[#size]; + static { + Generators.G.fill(Generators.G.ints(), $INPUT_A); + } + private static int $INPUT_B = #con1; + private static Object $GOLD = $test($INPUT_A.clone(), $INPUT_B); + + @Setup + public static Object[] $setup() { + // Must make sure to clone input arrays, if it is mutated in the test. + return new Object[] {$INPUT_A.clone(), $INPUT_B}; + } + + @Test + @Arguments(setup = "$setup") + public static Object $test(int[] a, int b) { + for (int i = 0; i < a.length; i++) { + int con = #con2; + a[i] = (a[i] * con) #op b; + } + return a; + } + + @Check(test = "$test") + public static void $check(Object result) { + Verify.checkEQ(result, $GOLD); + } + // --- $test end --- + """, + // Good to know: we can insert to the class hook, which is set for the + // TestFrameworkClass scope: + Hooks.CLASS_HOOK.insert(commentTemplate.asToken()) + )); + + // Create a test for each operator. + List ops = List.of("+", "-", "*", "&", "|"); + List testTemplateTokens = ops.stream().map(testTemplate::asToken).toList(); + + // Create the test class, which runs all testTemplateTokens. + return TestFrameworkClass.render( + // package and class name. + "p.xyz", "InnerTest", + // Set of imports. + Set.of("compiler.lib.generators.*", + "compiler.lib.verify.*"), + // classpath, so the Test VM has access to the compiled class files. + comp.getEscapedClassPathOfCompiledClasses(), + // The list of tests. + testTemplateTokens); + } +} From dd68829017c3adea4068d5311cab3fbef87b9577 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 12 Jun 2025 14:19:08 +0000 Subject: [PATCH 025/213] 8347273: C2: VerifyIterativeGVN for Ideal and Identity Reviewed-by: chagedorn, mhaessig --- src/hotspot/share/opto/c2_globals.hpp | 10 +- src/hotspot/share/opto/phaseX.cpp | 914 +++++++++++++++++- src/hotspot/share/opto/phaseX.hpp | 15 +- .../flags/jvmFlagConstraintsCompiler.cpp | 5 +- .../compiler/c2/TestVerifyIterativeGVN.java | 6 +- 5 files changed, 925 insertions(+), 25 deletions(-) diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index fd55f2fd666..227817612ce 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -678,10 +678,12 @@ "Print progress during Iterative Global Value Numbering") \ \ develop(uint, VerifyIterativeGVN, 0, \ - "Verify Iterative Global Value Numbering" \ - "=XY, with Y: verify Def-Use modifications during IGVN" \ - " X: verify that type(n) == n->Value() after IGVN" \ - "X and Y in 0=off; 1=on") \ + "Verify Iterative Global Value Numbering =DCBA, with:" \ + " D: verify Node::Identity did not miss opportunities" \ + " C: verify Node::Ideal did not miss opportunities" \ + " B: verify that type(n) == n->Value() after IGVN" \ + " A: verify Def-Use modifications during IGVN" \ + "Each can be 0=off or 1=on") \ constraint(VerifyIterativeGVNConstraintFunc, AtParse) \ \ develop(bool, TraceCISCSpill, false, \ diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 953afb0e830..1ba8e145e7d 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1072,7 +1072,11 @@ void PhaseIterGVN::optimize() { #ifdef ASSERT void PhaseIterGVN::verify_optimize() { - if (is_verify_Value()) { + assert(_worklist.size() == 0, "igvn worklist must be empty before verify"); + + if (is_verify_Value() || + is_verify_Ideal() || + is_verify_Identity()) { ResourceMark rm; Unique_Node_List worklist; bool failure = false; @@ -1080,7 +1084,10 @@ void PhaseIterGVN::verify_optimize() { worklist.push(C->root()); for (uint j = 0; j < worklist.size(); ++j) { Node* n = worklist.at(j); - failure |= verify_node_value(n); + if (is_verify_Value()) { failure |= verify_Value_for(n); } + if (is_verify_Ideal()) { failure |= verify_Ideal_for(n, false); } + if (is_verify_Ideal()) { failure |= verify_Ideal_for(n, true); } + if (is_verify_Identity()) { failure |= verify_Identity_for(n); } // traverse all inputs and outputs for (uint i = 0; i < n->req(); i++) { if (n->in(i) != nullptr) { @@ -1097,6 +1104,27 @@ void PhaseIterGVN::verify_optimize() { // in the verification code above if that is not possible for some reason (like Load nodes). assert(!failure, "Missed optimization opportunity in PhaseIterGVN"); } + + verify_empty_worklist(nullptr); +} + +void PhaseIterGVN::verify_empty_worklist(Node* node) { + // Verify that the igvn worklist is empty. If no optimization happened, then + // nothing needs to be on the worklist. + if (_worklist.size() == 0) { return; } + + stringStream ss; // Print as a block without tty lock. + for (uint j = 0; j < _worklist.size(); j++) { + Node* n = _worklist.at(j); + ss.print("igvn.worklist[%d] ", j); + n->dump("\n", false, &ss); + } + if (_worklist.size() != 0 && node != nullptr) { + ss.print_cr("Previously optimized:"); + node->dump("\n", false, &ss); + } + tty->print_cr("%s", ss.as_string()); + assert(false, "igvn worklist must still be empty after verify"); } // Check that type(n) == n->Value(), return true if we have a failure. @@ -1104,7 +1132,7 @@ void PhaseIterGVN::verify_optimize() { // (1) Integer "widen" changes, but the range is the same. // (2) LoadNode performs deep traversals. Load is not notified for changes far away. // (3) CmpPNode performs deep traversals if it compares oopptr. CmpP is not notified for changes far away. -bool PhaseIterGVN::verify_node_value(Node* n) { +bool PhaseIterGVN::verify_Value_for(Node* n) { // If we assert inside type(n), because the type is still a null, then maybe // the node never went through gvn.transform, which would be a bug. const Type* told = type(n); @@ -1149,15 +1177,873 @@ bool PhaseIterGVN::verify_node_value(Node* n) { // after loop-opts, so that should take care of many of these cases. return false; } - tty->cr(); - tty->print_cr("Missed Value optimization:"); - n->dump_bfs(1, nullptr, ""); - tty->print_cr("Current type:"); - told->dump_on(tty); - tty->cr(); - tty->print_cr("Optimized type:"); - tnew->dump_on(tty); - tty->cr(); + + stringStream ss; // Print as a block without tty lock. + ss.cr(); + ss.print_cr("Missed Value optimization:"); + n->dump_bfs(1, nullptr, "", &ss); + ss.print_cr("Current type:"); + told->dump_on(&ss); + ss.cr(); + ss.print_cr("Optimized type:"); + tnew->dump_on(&ss); + ss.cr(); + tty->print_cr("%s", ss.as_string()); + return true; +} + +// Check that all Ideal optimizations that could be done were done. +// Returns true if it found missed optimization opportunities and +// false otherwise (no missed optimization, or skipped verification). +bool PhaseIterGVN::verify_Ideal_for(Node* n, bool can_reshape) { + // First, we check a list of exceptions, where we skip verification, + // because there are known cases where Ideal can optimize after IGVN. + // Some may be expected and cannot be fixed, and others should be fixed. + switch (n->Opcode()) { + // RangeCheckNode::Ideal looks up the chain for about 999 nodes + // (see "Range-Check scan limit"). So, it is possible that something + // is optimized in that input subgraph, and the RangeCheck was not + // added to the worklist because it would be too expensive to walk + // down the graph for 1000 nodes and put all on the worklist. + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xbatch --version + case Op_RangeCheck: + return false; + + // IfNode::Ideal does: + // Node* prev_dom = search_identical(dist, igvn); + // which means we seach up the CFG, traversing at most up to a distance. + // If anything happens rather far away from the If, we may not put the If + // back on the worklist. + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xcomp --version + case Op_If: + return false; + + // IfNode::simple_subsuming + // Looks for dominating test that subsumes the current test. + // Notification could be difficult because of larger distance. + // + // Found with: + // runtime/exceptionMsgs/ArrayIndexOutOfBoundsException/ArrayIndexOutOfBoundsExceptionTest.java#id1 + // -XX:VerifyIterativeGVN=1110 + case Op_CountedLoopEnd: + return false; + + // LongCountedLoopEndNode::Ideal + // Probably same issue as above. + // + // Found with: + // compiler/predicates/assertion/TestAssertionPredicates.java#NoLoopPredicationXbatch + // -XX:StressLongCountedLoop=2000000 -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + case Op_LongCountedLoopEnd: + return false; + + // RegionNode::Ideal does "Skip around the useless IF diamond". + // 245 IfTrue === 244 + // 258 If === 245 257 + // 259 IfTrue === 258 [[ 263 ]] + // 260 IfFalse === 258 [[ 263 ]] + // 263 Region === 263 260 259 [[ 263 268 ]] + // to + // 245 IfTrue === 244 + // 263 Region === 263 245 _ [[ 263 268 ]] + // + // "Useless" means that there is no code in either branch of the If. + // I found a case where this was not done yet during IGVN. + // Why does the Region not get added to IGVN worklist when the If diamond becomes useless? + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xcomp --version + case Op_Region: + return false; + + // In AddNode::Ideal, we call "commute", which swaps the inputs so + // that smaller idx are first. Tracking it back, it led me to + // PhaseIdealLoop::remix_address_expressions which swapped the edges. + // + // Example: + // Before PhaseIdealLoop::remix_address_expressions + // 154 AddI === _ 12 144 + // After PhaseIdealLoop::remix_address_expressions + // 154 AddI === _ 144 12 + // After AddNode::Ideal + // 154 AddI === _ 12 144 + // + // I suspect that the node should be added to the IGVN worklist after + // PhaseIdealLoop::remix_address_expressions + // + // This is the only case I looked at, there may be others. Found like this: + // java -XX:VerifyIterativeGVN=0100 -Xbatch --version + // + // The following hit the same logic in PhaseIdealLoop::remix_address_expressions. + // + // Note: currently all of these fail also for other reasons, for example + // because of "commute" doing the reordering with the phi below. Once + // that is resolved, we can come back to this issue here. + // + // case Op_AddD: + // case Op_AddI: + // case Op_AddL: + // case Op_AddF: + // case Op_MulI: + // case Op_MulL: + // case Op_MulF: + // case Op_MulD: + // if (n->in(1)->_idx > n->in(2)->_idx) { + // // Expect "commute" to revert this case. + // return false; + // } + // break; // keep verifying + + // AddFNode::Ideal calls "commute", which can reorder the inputs for this: + // Check for tight loop increments: Loop-phi of Add of loop-phi + // It wants to take the phi into in(1): + // 471 Phi === 435 38 390 + // 390 AddF === _ 471 391 + // + // Other Associative operators are also affected equally. + // + // Investigate why this does not happen earlier during IGVN. + // + // Found with: + // test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java + // -XX:VerifyIterativeGVN=1110 + case Op_AddD: + //case Op_AddI: // Also affected for other reasons, see case further down. + //case Op_AddL: // Also affected for other reasons, see case further down. + case Op_AddF: + case Op_MulI: + case Op_MulL: + case Op_MulF: + case Op_MulD: + case Op_MinF: + case Op_MinD: + case Op_MaxF: + case Op_MaxD: + // XorINode::Ideal + // Found with: + // compiler/intrinsics/chacha/TestChaCha20.java + // -XX:VerifyIterativeGVN=1110 + case Op_XorI: + case Op_XorL: + // It seems we may have similar issues with the HF cases. + // Found with aarch64: + // compiler/vectorization/TestFloat16VectorOperations.java + // -XX:VerifyIterativeGVN=1110 + case Op_AddHF: + case Op_MulHF: + case Op_MaxHF: + case Op_MinHF: + return false; + + // In MulNode::Ideal the edges can be swapped to help value numbering: + // + // // We are OK if right is a constant, or right is a load and + // // left is a non-constant. + // if( !(t2->singleton() || + // (in(2)->is_Load() && !(t1->singleton() || in(1)->is_Load())) ) ) { + // if( t1->singleton() || // Left input is a constant? + // // Otherwise, sort inputs (commutativity) to help value numbering. + // (in(1)->_idx > in(2)->_idx) ) { + // swap_edges(1, 2); + // + // Why was this not done earlier during IGVN? + // + // Found with: + // test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithG1.java + // -XX:VerifyIterativeGVN=1110 + case Op_AndI: + // Same for AndL. + // Found with: + // compiler/intrinsics/bigInteger/MontgomeryMultiplyTest.java + // -XX:VerifyIterativeGVN=1110 + case Op_AndL: + return false; + + // SubLNode::Ideal does transform like: + // Convert "c1 - (y+c0)" into "(c1-c0) - y" + // + // In IGVN before verification: + // 8423 ConvI2L === _ 3519 [[ 8424 ]] #long:-2 + // 8422 ConvI2L === _ 8399 [[ 8424 ]] #long:3..256:www + // 8424 AddL === _ 8422 8423 [[ 8383 ]] !orig=[8382] + // 8016 ConL === 0 [[ 8383 ]] #long:0 + // 8383 SubL === _ 8016 8424 [[ 8156 ]] !orig=[8154] + // + // And then in verification: + // 8338 ConL === 0 [[ 8339 8424 ]] #long:-2 <----- Was constant folded. + // 8422 ConvI2L === _ 8399 [[ 8424 ]] #long:3..256:www + // 8424 AddL === _ 8422 8338 [[ 8383 ]] !orig=[8382] + // 8016 ConL === 0 [[ 8383 ]] #long:0 + // 8383 SubL === _ 8016 8424 [[ 8156 ]] !orig=[8154] + // + // So the form changed from: + // c1 - (y + [8423 ConvI2L]) + // to + // c1 - (y + -2) + // but the SubL was not added to the IGVN worklist. Investigate why. + // There could be other issues too. + // + // There seems to be a related AddL IGVN optimization that triggers + // the same SubL optimization, so investigate that too. + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xcomp --version + case Op_SubL: + return false; + + // SubINode::Ideal does + // Convert "x - (y+c0)" into "(x-y) - c0" AND + // Convert "c1 - (y+c0)" into "(c1-c0) - y" + // + // Investigate why this does not yet happen during IGVN. + // + // Found with: + // test/hotspot/jtreg/compiler/c2/IVTest.java + // -XX:VerifyIterativeGVN=1110 + case Op_SubI: + return false; + + // AddNode::IdealIL does transform like: + // Convert x + (con - y) into "(x - y) + con" + // + // In IGVN before verification: + // 8382 ConvI2L + // 8381 ConvI2L === _ 791 [[ 8383 ]] #long:0 + // 8383 SubL === _ 8381 8382 + // 8168 ConvI2L + // 8156 AddL === _ 8168 8383 [[ 8158 ]] + // + // And then in verification: + // 8424 AddL + // 8016 ConL === 0 [[ 8383 ]] #long:0 <--- Was constant folded. + // 8383 SubL === _ 8016 8424 + // 8168 ConvI2L + // 8156 AddL === _ 8168 8383 [[ 8158 ]] + // + // So the form changed from: + // x + (ConvI2L(0) - [8382 ConvI2L]) + // to + // x + (0 - [8424 AddL]) + // but the AddL was not added to the IGVN worklist. Investigate why. + // There could be other issues, too. For example with "commute", see above. + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xcomp --version + case Op_AddL: + return false; + + // SubTypeCheckNode::Ideal calls SubTypeCheckNode::verify_helper, which does + // Node* cmp = phase->transform(new CmpPNode(subklass, in(SuperKlass))); + // record_for_cleanup(cmp, phase); + // This verification code in the Ideal code creates new nodes, and checks + // if they fold in unexpected ways. This means some nodes are created and + // added to the worklist, even if the SubTypeCheck is not optimized. This + // goes agains the assumption of the verification here, which assumes that + // if the node is not optimized, then no new nodes should be created, and + // also no nodes should be added to the worklist. + // I see two options: + // 1) forbid what verify_helper does, because for each Ideal call it + // uses memory and that is suboptimal. But it is not clear how that + // verification can be done otherwise. + // 2) Special case the verification here. Probably the new nodes that + // were just created are dead, i.e. they are not connected down to + // root. We could verify that, and remove those nodes from the graph + // by setting all their inputs to nullptr. And of course we would + // have to remove those nodes from the worklist. + // Maybe there are other options too, I did not dig much deeper yet. + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xbatch --version + case Op_SubTypeCheck: + return false; + + // LoopLimitNode::Ideal when stride is constant power-of-2, we can do a lowering + // to other nodes: Conv, Add, Sub, Mul, And ... + // + // 107 ConI === 0 [[ ... ]] #int:2 + // 84 LoadRange === _ 7 83 + // 50 ConI === 0 [[ ... ]] #int:0 + // 549 LoopLimit === _ 50 84 107 + // + // I stepped backward, to see how the node was generated, and I found that it was + // created in PhaseIdealLoop::exact_limit and not changed since. It is added to the + // IGVN worklist. I quickly checked when it goes into LoopLimitNode::Ideal after + // that, and it seems we want to skip lowering it until after loop-opts, but never + // add call record_for_post_loop_opts_igvn. This would be an easy fix, but there + // could be other issues too. + // + // Fond with: + // java -XX:VerifyIterativeGVN=0100 -Xcomp --version + case Op_LoopLimit: + return false; + + // PhiNode::Ideal calls split_flow_path, which tries to do this: + // "This optimization tries to find two or more inputs of phi with the same constant + // value. It then splits them into a separate Phi, and according Region." + // + // Example: + // 130 DecodeN === _ 129 + // 50 ConP === 0 [[ 18 91 99 18 ]] #null + // 18 Phi === 14 50 130 50 [[ 133 ]] #java/lang/Object * Oop:java/lang/Object * + // + // turns into: + // + // 50 ConP === 0 [[ 99 91 18 ]] #null + // 130 DecodeN === _ 129 [[ 18 ]] + // 18 Phi === 14 130 50 [[ 133 ]] #java/lang/Object * Oop:java/lang/Object * + // + // We would have to investigate why this optimization does not happen during IGVN. + // There could also be other issues - I did not investigate further yet. + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xcomp --version + case Op_Phi: + return false; + + // MemBarNode::Ideal does "Eliminate volatile MemBars for scalar replaced objects". + // For examle "The allocated object does not escape". + // + // It seems the difference to earlier calls to MemBarNode::Ideal, is that there + // alloc->as_Allocate()->does_not_escape_thread() returned false, but in verification + // it returned true. Why does the MemBarStoreStore not get added to the IGVN + // worklist when this change happens? + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xcomp --version + case Op_MemBarStoreStore: + return false; + + // ConvI2LNode::Ideal converts + // 648 AddI === _ 583 645 [[ 661 ]] + // 661 ConvI2L === _ 648 [[ 664 ]] #long:0..maxint-1:www + // into + // 772 ConvI2L === _ 645 [[ 773 ]] #long:-120..maxint-61:www + // 771 ConvI2L === _ 583 [[ 773 ]] #long:60..120:www + // 773 AddL === _ 771 772 [[ ]] + // + // We have to investigate why this does not happen during IGVN in this case. + // There could also be other issues - I did not investigate further yet. + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xcomp --version + case Op_ConvI2L: + return false; + + // AddNode::IdealIL can do this transform (and similar other ones): + // Convert "a*b+a*c into a*(b+c) + // The example had AddI(MulI(a, b), MulI(a, c)). Why did this not happen + // during IGVN? There was a mutation for one of the MulI, and only + // after that the pattern was as needed for the optimization. The MulI + // was added to the IGVN worklist, but not the AddI. This probably + // can be fixed by adding the correct pattern in add_users_of_use_to_worklist. + // + // Found with: + // test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java + // -XX:VerifyIterativeGVN=1110 + case Op_AddI: + return false; + + // ArrayCopyNode::Ideal + // calls ArrayCopyNode::prepare_array_copy + // calls Compile::conv_I2X_index -> is called with sizetype = intcon(0), I think that + // is not expected, and we create a range int:0..-1 + // calls Compile::constrained_convI2L -> creates ConvI2L(intcon(1), int:0..-1) + // note: the type is already empty! + // calls PhaseIterGVN::transform + // calls PhaseIterGVN::transform_old + // calls PhaseIterGVN::subsume_node -> subsume ConvI2L with TOP + // calls Unique_Node_List::push -> pushes TOP to worklist + // + // Once we get back to ArrayCopyNode::prepare_array_copy, we get back TOP, and + // return false. This means we eventually return nullptr from ArrayCopyNode::Ideal. + // + // Question: is it ok to push anything to the worklist during ::Ideal, if we will + // return nullptr, indicating nothing happened? + // Is it smart to do transform in Compile::constrained_convI2L, and then + // check for TOP in calls ArrayCopyNode::prepare_array_copy? + // Should we just allow TOP to land on the worklist, as an exception? + // + // Found with: + // compiler/arraycopy/TestArrayCopyAsLoadsStores.java + // -XX:VerifyIterativeGVN=1110 + case Op_ArrayCopy: + return false; + + // CastLLNode::Ideal + // calls ConstraintCastNode::optimize_integer_cast -> pushes CastLL through SubL + // + // Could be a notification issue, where updates inputs of CastLL do not notify + // down through SubL to CastLL. + // + // Found With: + // compiler/c2/TestMergeStoresMemorySegment.java#byte-array + // -XX:VerifyIterativeGVN=1110 + case Op_CastLL: + return false; + + // Similar case happens to CastII + // + // Found With: + // compiler/c2/TestScalarReplacementMaxLiveNodes.java + // -XX:VerifyIterativeGVN=1110 + case Op_CastII: + return false; + + // MaxLNode::Ideal + // calls AddNode::Ideal + // calls commute -> decides to swap edges + // + // Another notification issue, because we check inputs of inputs? + // MaxL -> Phi -> Loop + // MaxL -> Phi -> MaxL + // + // Found with: + // compiler/c2/irTests/TestIfMinMax.java + // -XX:VerifyIterativeGVN=1110 + case Op_MaxL: + case Op_MinL: + return false; + + // OrINode::Ideal + // calls AddNode::Ideal + // calls commute -> left is Load, right not -> commute. + // + // Not sure why notification does not work here, seems like + // the depth is only 1, so it should work. Needs investigation. + // + // Found with: + // compiler/codegen/TestCharVect2.java#id0 + // -XX:VerifyIterativeGVN=1110 + case Op_OrI: + case Op_OrL: + return false; + + // Bool -> constant folded to 1. + // Issue with notification? + // + // Found with: + // compiler/c2/irTests/TestVectorizationMismatchedAccess.java + // -XX:VerifyIterativeGVN=1110 + case Op_Bool: + return false; + + // LShiftLNode::Ideal + // Looks at pattern: "(x + x) << c0", converts it to "x << (c0 + 1)" + // Probably a notification issue. + // + // Found with: + // compiler/conversions/TestMoveConvI2LOrCastIIThruAddIs.java + // -ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -XX:-TieredCompilation -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + case Op_LShiftL: + return false; + + // LShiftINode::Ideal + // pattern: ((x + con1) << con2) -> x << con2 + con1 << con2 + // Could be issue with notification of inputs of inputs + // + // Side-note: should cases like these not be shared between + // LShiftI and LShiftL? + // + // Found with: + // compiler/escapeAnalysis/Test6689060.java + // -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 -ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -XX:-TieredCompilation -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + case Op_LShiftI: + return false; + + // AddPNode::Ideal seems to do set_req without removing lock first. + // Found with various vector tests tier1-tier3. + case Op_AddP: + return false; + + // StrIndexOfNode::Ideal + // Found in tier1-3. + case Op_StrIndexOf: + case Op_StrIndexOfChar: + return false; + + // StrEqualsNode::Identity + // + // Found (linux x64 only?) with: + // serviceability/sa/ClhsdbThreadContext.java + // -XX:+UnlockExperimentalVMOptions -XX:LockingMode=1 -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + case Op_StrEquals: + return false; + + // AryEqNode::Ideal + // Not investigated. Reshapes itself and adds lots of nodes to the worklist. + // + // Found with: + // vmTestbase/vm/mlvm/meth/stress/compiler/i2c_c2i/Test.java + // -XX:+UnlockDiagnosticVMOptions -XX:-TieredCompilation -XX:+StressUnstableIfTraps -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + case Op_AryEq: + return false; + + // MergeMemNode::Ideal + // Found in tier1-3. Did not investigate further yet. + case Op_MergeMem: + return false; + + // URShiftINode::Ideal + // Found in tier1-3. Did not investigate further yet. + case Op_URShiftI: + return false; + + // CMoveINode::Ideal + // Found in tier1-3. Did not investigate further yet. + case Op_CMoveI: + return false; + + // CmpPNode::Ideal calls isa_const_java_mirror + // and generates new constant nodes, even if no progress is made. + // We can probably rewrite this so that only types are generated. + // It seems that object types are not hashed, we could investigate + // if that is an option as well. + // + // Found with: + // java -XX:VerifyIterativeGVN=1110 -Xcomp --version + case Op_CmpP: + return false; + + // MinINode::Ideal + // Did not investigate, but there are some patterns that might + // need more notification. + case Op_MinI: + case Op_MaxI: // preemptively removed it as well. + return false; + } + + if (n->is_Load()) { + // LoadNode::Ideal uses tries to find an earlier memory state, and + // checks can_see_stored_value for it. + // + // Investigate why this was not already done during IGVN. + // A similar issue happens with Identity. + // + // There seem to be other cases where loads go up some steps, like + // LoadNode::Ideal going up 10x steps to find dominating load. + // + // Found with: + // test/hotspot/jtreg/compiler/arraycopy/TestCloneAccess.java + // -XX:VerifyIterativeGVN=1110 + return false; + } + + if (n->is_Store()) { + // StoreNode::Ideal can do this: + // // Capture an unaliased, unconditional, simple store into an initializer. + // // Or, if it is independent of the allocation, hoist it above the allocation. + // That replaces the Store with a MergeMem. + // + // We have to investigate why this does not happen during IGVN in this case. + // There could also be other issues - I did not investigate further yet. + // + // Found with: + // java -XX:VerifyIterativeGVN=0100 -Xcomp --version + return false; + } + + if (n->is_Vector()) { + // VectorNode::Ideal swaps edges, but only for ops + // that are deemed commutable. But swap_edges + // requires the hash to be invariant when the edges + // are swapped, which is not implemented for these + // vector nodes. This seems not to create any trouble + // usually, but we can also get graphs where in the + // end the nodes are not all commuted, so there is + // definitively an issue here. + // + // Probably we have two options: kill the hash, or + // properly make the hash commutation friendly. + // + // Found with: + // compiler/vectorapi/TestMaskedMacroLogicVector.java + // -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 -XX:+UseParallelGC -XX:+UseNUMA + return false; + } + + if (n->is_Region()) { + // LoopNode::Ideal calls RegionNode::Ideal. + // CountedLoopNode::Ideal calls RegionNode::Ideal too. + // But I got an issue because RegionNode::optimize_trichotomy + // then modifies another node, and pushes nodes to the worklist + // Not sure if this is ok, modifying another node like that. + // Maybe it is, then we need to look into what to do with + // the nodes that are now on the worklist, maybe just clear + // them out again. But maybe modifying other nodes like that + // is also bad design. In the end, we return nullptr for + // the current CountedLoop. But the extra nodes on the worklist + // trip the asserts later on. + // + // Found with: + // compiler/eliminateAutobox/TestShortBoxing.java + // -ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -XX:-TieredCompilation -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + return false; + } + + if (n->is_CallJava()) { + // CallStaticJavaNode::Ideal + // Led to a crash: + // assert((is_CallStaticJava() && cg->is_mh_late_inline()) || (is_CallDynamicJava() && cg->is_virtual_late_inline())) failed: mismatch + // + // Did not investigate yet, could be a bug. + // Or maybe it does not expect to be called during verification. + // + // Found with: + // test/jdk/jdk/incubator/vector/VectorRuns.java + // -XX:VerifyIterativeGVN=1110 + + // CallDynamicJavaNode::Ideal, and I think also for CallStaticJavaNode::Ideal + // and possibly their subclasses. + // During late inlining it can call CallJavaNode::register_for_late_inline + // That means we do more rounds of late inlining, but might fail. + // Then we do IGVN again, and register the node again for late inlining. + // This creates an endless cycle. Everytime we try late inlining, we + // are also creating more nodes, especially SafePoint and MergeMem. + // These nodes are immediately rejected when the inlining fails in the + // do_late_inline_check, but they still grow the memory, until we hit + // the MemLimit and crash. + // The assumption here seems that CallDynamicJavaNode::Ideal does not get + // called repeatedly, and eventually we terminate. I fear this is not + // a great assumption to make. We should investigate more. + // + // Found with: + // compiler/loopopts/superword/TestDependencyOffsets.java#vanilla-U + // -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + return false; + } + + // The number of nodes shoud not increase. + uint old_unique = C->unique(); + + Node* i = n->Ideal(this, can_reshape); + // If there was no new Idealization, we are probably happy. + if (i == nullptr) { + if (old_unique < C->unique()) { + stringStream ss; // Print as a block without tty lock. + ss.cr(); + ss.print_cr("Ideal optimization did not make progress but created new unused nodes."); + ss.print_cr(" old_unique = %d, unique = %d", old_unique, C->unique()); + n->dump_bfs(1, nullptr, "", &ss); + tty->print_cr("%s", ss.as_string()); + return true; + } + + verify_empty_worklist(n); + + // Everything is good. + return false; + } + + // We just saw a new Idealization which was not done during IGVN. + stringStream ss; // Print as a block without tty lock. + ss.cr(); + ss.print_cr("Missed Ideal optimization (can_reshape=%s):", can_reshape ? "true": "false"); + if (i == n) { + ss.print_cr("The node was reshaped by Ideal."); + } else { + ss.print_cr("The node was replaced by Ideal."); + ss.print_cr("Old node:"); + n->dump_bfs(1, nullptr, "", &ss); + } + ss.print_cr("The result after Ideal:"); + i->dump_bfs(1, nullptr, "", &ss); + tty->print_cr("%s", ss.as_string()); + return true; +} + +// Check that all Identity optimizations that could be done were done. +// Returns true if it found missed optimization opportunities and +// false otherwise (no missed optimization, or skipped verification). +bool PhaseIterGVN::verify_Identity_for(Node* n) { + // First, we check a list of exceptions, where we skip verification, + // because there are known cases where Ideal can optimize after IGVN. + // Some may be expected and cannot be fixed, and others should be fixed. + switch (n->Opcode()) { + // SafePointNode::Identity can remove SafePoints, but wants to wait until + // after loopopts: + // // Transforming long counted loops requires a safepoint node. Do not + // // eliminate a safepoint until loop opts are over. + // if (in(0)->is_Proj() && !phase->C->major_progress()) { + // + // I think the check for major_progress does delay it until after loopopts + // but it does not ensure that the node is on the IGVN worklist after + // loopopts. I think we should try to instead check for + // phase->C->post_loop_opts_phase() and call record_for_post_loop_opts_igvn. + // + // Found with: + // java -XX:VerifyIterativeGVN=1000 -Xcomp --version + case Op_SafePoint: + return false; + + // MergeMemNode::Identity replaces the MergeMem with its base_memory if it + // does not record any other memory splits. + // + // I did not deeply investigate, but it looks like MergeMemNode::Identity + // never got called during IGVN for this node, investigate why. + // + // Found with: + // java -XX:VerifyIterativeGVN=1000 -Xcomp --version + case Op_MergeMem: + return false; + + // ConstraintCastNode::Identity finds casts that are the same, except that + // the control is "higher up", i.e. dominates. The call goes via + // ConstraintCastNode::dominating_cast to PhaseGVN::is_dominator_helper, + // which traverses up to 100 idom steps. If anything gets optimized somewhere + // away from the cast, but within 100 idom steps, the cast may not be + // put on the IGVN worklist any more. + // + // Found with: + // java -XX:VerifyIterativeGVN=1000 -Xcomp --version + case Op_CastPP: + case Op_CastII: + case Op_CastLL: + return false; + + // Same issue for CheckCastPP, uses ConstraintCastNode::Identity and + // checks dominator, which may be changed, but too far up for notification + // to work. + // + // Found with: + // compiler/c2/irTests/TestSkeletonPredicates.java + // -XX:VerifyIterativeGVN=1110 + case Op_CheckCastPP: + return false; + + // In SubNode::Identity, we do: + // Convert "(X+Y) - Y" into X and "(X+Y) - X" into Y + // In the example, the AddI had an input replaced, the AddI is + // added to the IGVN worklist, but the SubI is one link further + // down and is not added. I checked add_users_of_use_to_worklist + // where I would expect the SubI would be added, and I cannot + // find the pattern, only this one: + // If changed AddI/SubI inputs, check CmpU for range check optimization. + // + // Fix this "notification" issue and check if there are any other + // issues. + // + // Found with: + // java -XX:VerifyIterativeGVN=1000 -Xcomp --version + case Op_SubI: + case Op_SubL: + return false; + + // PhiNode::Identity checks for patterns like: + // r = (x != con) ? x : con; + // that can be constant folded to "x". + // + // Call goes through PhiNode::is_cmove_id and CMoveNode::is_cmove_id. + // I suspect there was some earlier change to one of the inputs, but + // not all relevant outputs were put on the IGVN worklist. + // + // Found with: + // test/hotspot/jtreg/gc/stress/gcbasher/TestGCBasherWithG1.java + // -XX:VerifyIterativeGVN=1110 + case Op_Phi: + return false; + + // ConvI2LNode::Identity does + // convert I2L(L2I(x)) => x + // + // Investigate why this did not already happen during IGVN. + // + // Found with: + // compiler/loopopts/superword/TestDependencyOffsets.java#vanilla-A + // -XX:VerifyIterativeGVN=1110 + case Op_ConvI2L: + return false; + + // MaxNode::find_identity_operation + // Finds patterns like Max(A, Max(A, B)) -> Max(A, B) + // This can be a 2-hop search, so maybe notification is not + // good enough. + // + // Found with: + // compiler/codegen/TestBooleanVect.java + // -XX:VerifyIterativeGVN=1110 + case Op_MaxL: + case Op_MinL: + case Op_MaxI: + case Op_MinI: + case Op_MaxF: + case Op_MinF: + case Op_MaxHF: + case Op_MinHF: + case Op_MaxD: + case Op_MinD: + return false; + + + // AddINode::Identity + // Converts (x-y)+y to x + // Could be issue with notification + // + // Turns out AddL does the same. + // + // Found with: + // compiler/c2/Test6792161.java + // -ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -XX:-TieredCompilation -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + case Op_AddI: + case Op_AddL: + return false; + + // AbsINode::Identity + // Not investigated yet. + case Op_AbsI: + return false; + } + + if (n->is_Load()) { + // LoadNode::Identity tries to look for an earlier store value via + // can_see_stored_value. I found an example where this led to + // an Allocation, where we could assume the value was still zero. + // So the LoadN can be replaced with a zerocon. + // + // Investigate why this was not already done during IGVN. + // A similar issue happens with Ideal. + // + // Found with: + // java -XX:VerifyIterativeGVN=1000 -Xcomp --version + return false; + } + + if (n->is_Store()) { + // StoreNode::Identity + // Not investigated, but found missing optimization for StoreI. + // Looks like a StoreI is replaced with an InitializeNode. + // + // Found with: + // applications/ctw/modules/java_base_2.java + // -ea -esa -XX:CompileThreshold=100 -XX:+UnlockExperimentalVMOptions -server -XX:-TieredCompilation -Djava.awt.headless=true -XX:+IgnoreUnrecognizedVMOptions -XX:VerifyIterativeGVN=1110 + return false; + } + + if (n->is_Vector()) { + // Found with tier1-3. Not investigated yet. + // The observed issue was with AndVNode::Identity + return false; + } + + Node* i = n->Identity(this); + // If we cannot find any other Identity, we are happy. + if (i == n) { + verify_empty_worklist(n); + return false; + } + + // The verification just found a new Identity that was not found during IGVN. + stringStream ss; // Print as a block without tty lock. + ss.cr(); + ss.print_cr("Missed Identity optimization:"); + ss.print_cr("Old node:"); + n->dump_bfs(1, nullptr, "", &ss); + ss.print_cr("New node:"); + i->dump_bfs(1, nullptr, "", &ss); + tty->print_cr("%s", ss.as_string()); return true; } #endif @@ -1890,12 +2776,12 @@ void PhaseCCP::analyze() { #ifdef ASSERT // For every node n on verify list, check if type(n) == n->Value() -// We have a list of exceptions, see comments in verify_node_value. +// We have a list of exceptions, see comments in verify_Value_for. void PhaseCCP::verify_analyze(Unique_Node_List& worklist_verify) { bool failure = false; while (worklist_verify.size()) { Node* n = worklist_verify.pop(); - failure |= verify_node_value(n); + failure |= verify_Value_for(n); } // If we get this assert, check why the reported nodes were not processed again in CCP. // We should either make sure that these nodes are properly added back to the CCP worklist diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index c2a0f0dbb77..648e911e783 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -494,7 +494,10 @@ class PhaseIterGVN : public PhaseGVN { void optimize(); #ifdef ASSERT void verify_optimize(); - bool verify_node_value(Node* n); + bool verify_Value_for(Node* n); + bool verify_Ideal_for(Node* n, bool can_reshape); + bool verify_Identity_for(Node* n); + void verify_empty_worklist(Node* n); #endif #ifndef PRODUCT @@ -593,6 +596,14 @@ class PhaseIterGVN : public PhaseGVN { // '-XX:VerifyIterativeGVN=10' return ((VerifyIterativeGVN % 100) / 10) == 1; } + static bool is_verify_Ideal() { + // '-XX:VerifyIterativeGVN=100' + return ((VerifyIterativeGVN % 1000) / 100) == 1; + } + static bool is_verify_Identity() { + // '-XX:VerifyIterativeGVN=1000' + return ((VerifyIterativeGVN % 10000) / 1000) == 1; + } protected: // Sub-quadratic implementation of '-XX:VerifyIterativeGVN=1' (Use-Def verification). julong _verify_counter; diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp index d9972b21ea1..18aa4a56d71 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp @@ -299,8 +299,9 @@ JVMFlag::Error TypeProfileLevelConstraintFunc(uint value, bool verbose) { } JVMFlag::Error VerifyIterativeGVNConstraintFunc(uint value, bool verbose) { + const int max_modes = 4; uint original_value = value; - for (int i = 0; i < 2; i++) { + for (int i = 0; i < max_modes; i++) { if (value % 10 > 1) { JVMFlag::printError(verbose, "Invalid value (" UINT32_FORMAT ") " @@ -312,7 +313,7 @@ JVMFlag::Error VerifyIterativeGVNConstraintFunc(uint value, bool verbose) { if (value != 0) { JVMFlag::printError(verbose, "Invalid value (" UINT32_FORMAT ") " - "for VerifyIterativeGVN: maximal 2 digits\n", original_value); + "for VerifyIterativeGVN: maximal %d digits\n", original_value, max_modes); return JVMFlag::VIOLATES_CONSTRAINT; } return JVMFlag::SUCCESS; diff --git a/test/hotspot/jtreg/compiler/c2/TestVerifyIterativeGVN.java b/test/hotspot/jtreg/compiler/c2/TestVerifyIterativeGVN.java index f3f589f8fb1..83f3540226f 100644 --- a/test/hotspot/jtreg/compiler/c2/TestVerifyIterativeGVN.java +++ b/test/hotspot/jtreg/compiler/c2/TestVerifyIterativeGVN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,9 @@ * @test * @bug 8238756 * @requires vm.debug == true & vm.flavor == "server" - * @summary Run with -Xcomp to test -XX:VerifyIterativeGVN=11 in debug builds. + * @summary Run with -Xcomp to test -XX:VerifyIterativeGVN=1111 in debug builds. * - * @run main/othervm/timeout=300 -Xbatch -Xcomp -XX:VerifyIterativeGVN=11 compiler.c2.TestVerifyIterativeGVN + * @run main/othervm/timeout=300 -Xcomp -XX:VerifyIterativeGVN=1111 compiler.c2.TestVerifyIterativeGVN */ package compiler.c2; From fae9c7a3f04f85aeb9e03c5c9c15fda6405ee989 Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Thu, 12 Jun 2025 14:46:39 +0000 Subject: [PATCH 026/213] 8351661: NMT: VMATree should support separate call-stacks for reserve and commit operations Reviewed-by: gziemski, jsjolen --- src/hotspot/share/logging/logTag.hpp | 1 + src/hotspot/share/nmt/memoryFileTracker.cpp | 2 +- .../share/nmt/nmtNativeCallStackStorage.hpp | 5 +- src/hotspot/share/nmt/vmatree.cpp | 751 +++++++-- src/hotspot/share/nmt/vmatree.hpp | 111 +- test/hotspot/gtest/nmt/test_vmatree.cpp | 1430 +++++++++++++++-- 6 files changed, 2032 insertions(+), 268 deletions(-) diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index 34927a9b613..9edf81d3f27 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -216,6 +216,7 @@ class outputStream; LOG_TAG(valuebasedclasses) \ LOG_TAG(verification) \ LOG_TAG(verify) \ + LOG_TAG(vmatree) \ LOG_TAG(vmmutex) \ LOG_TAG(vmoperation) \ LOG_TAG(vmthread) \ diff --git a/src/hotspot/share/nmt/memoryFileTracker.cpp b/src/hotspot/share/nmt/memoryFileTracker.cpp index d753a57ede7..4ffcb535e4b 100644 --- a/src/hotspot/share/nmt/memoryFileTracker.cpp +++ b/src/hotspot/share/nmt/memoryFileTracker.cpp @@ -91,7 +91,7 @@ void MemoryFileTracker::print_report_on(const MemoryFile* file, outputStream* st NMTUtil::tag_to_name(prev->val().out.mem_tag())); { StreamIndentor si(stream, 4); - _stack_storage.get(prev->val().out.stack()).print_on(stream); + _stack_storage.get(prev->val().out.reserved_stack()).print_on(stream); } stream->cr(); } diff --git a/src/hotspot/share/nmt/nmtNativeCallStackStorage.hpp b/src/hotspot/share/nmt/nmtNativeCallStackStorage.hpp index 258c3284a18..85e044c1a45 100644 --- a/src/hotspot/share/nmt/nmtNativeCallStackStorage.hpp +++ b/src/hotspot/share/nmt/nmtNativeCallStackStorage.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,11 +43,8 @@ class NativeCallStackStorage : public CHeapObjBase { public: using StackIndex = int; - -private: constexpr static const StackIndex invalid = std::numeric_limits::max() - 1; -public: static bool equals(const StackIndex a, const StackIndex b) { return a == b; } diff --git a/src/hotspot/share/nmt/vmatree.cpp b/src/hotspot/share/nmt/vmatree.cpp index 3352a6e5cd4..48febdce7c2 100644 --- a/src/hotspot/share/nmt/vmatree.cpp +++ b/src/hotspot/share/nmt/vmatree.cpp @@ -28,21 +28,228 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/growableArray.hpp" -const VMATree::RegionData VMATree::empty_regiondata{NativeCallStackStorage::StackIndex{}, mtNone}; + +// Semantics +// This tree is used to store and track the state of virtual memory regions. +// The nodes in the tree are key-value pairs where the key is the memory address and the value is the State of the memory regions. +// The State of a region describes whether the region is released, reserved or committed, which MemTag it has and where in +// Hotspot (using call-stacks) it is reserved or committed. +// Each node holds the State of the regions to its left and right. Each memory region is described by two +// memory addresses for its start and end. +// For example, to describe the region that starts at memory address 0xA000 with size 0x1000, there will be two nodes +// with the keys 0xA000 (node A) and 0xB000 (node B) in the tree. The value of the key-value pairs of node A and +// node B describe the region's State, using right of A and left of B (<--left--A--right-->.....<--left--B--right-->...). +// +// Virtual memory can be reserved, committed, uncommitted and released. For each operation a request +// () is sent to the tree to handle. +// +// The expected changes are described here for each operation: +// +// ### Reserve a region +// When a region is reserved, all the overlapping regions in the tree should: +// - be marked as Reserved +// - take MemTag of the operation +// - store call-stack of the request to the reserve call-stack +// - clear commit call-stack +// +// ### Commit a region +// When a region is committed, all the overlapping regions in the tree should: +// - be marked as Committed +// - take MemTag of the operation or MemTag of the existing region, depends on which-tag-to-use in the request +// - if the region is in Released state +// - mark the region as both Reserved and Committed +// - store the call-stack of the request to the reserve call-stack +// - store the call-stack of the request to the commit call-stack +// +// ### Uncommit a region +// When a region is uncommitted, all the overlapping regions in the tree should: +// - be ignored if the region is in Released state +// - be marked as Reserved +// - not change the MemTag +// - not change the reserve call-stack +// - clear commit call-stack +// +// ### Release a region +// When a region is released, all the overlapping regions in the tree should: +// - be marked as Released +// - set the MemTag to mtNone +// - clear both reserve and commit call-stack +// +// --- Accounting +// After each operation, the tree should be able to report how much memory is reserved or committed per MemTag. +// So for each region that changes to a new State, the report should contain (separately for each tag) the amount +// of reserve and commit that are changed (increased or decreased) due to the operation. + +const VMATree::RegionData VMATree::empty_regiondata{NativeCallStackStorage::invalid, mtNone}; const char* VMATree::statetype_strings[3] = { - "reserved", "committed", "released", + "released", "reserved", "committed" }; -VMATree::SummaryDiff VMATree::register_mapping(position A, position B, StateType state, +VMATree::SIndex VMATree::get_new_reserve_callstack(const SIndex es, const StateType ex, const RequestInfo& req) const { + const SIndex ES = NativeCallStackStorage::invalid; // Empty Stack + const SIndex rq = req.callstack; + const int op = req.op_to_index(); + const Operation oper = req.op(); + assert(op >= 0 && op < 4, "should be"); + assert(op >= 0 && op < 4, "should be"); + // existing state + SIndex result[4][3] = {// Rl Rs C + {ES, ES, ES}, // op == Release + {rq, rq, rq}, // op == Reserve + {es, es, es}, // op == Commit + {es, es, es} // op == Uncommit + }; + // When committing a Released region, the reserve-call-stack of the region should also be as what is in the request + if (oper == Operation::Commit && ex == StateType::Released) { + return rq; + } else { + return result[op][state_to_index(ex)]; + } +} + +VMATree::SIndex VMATree::get_new_commit_callstack(const SIndex es, const StateType ex, const RequestInfo& req) const { + const SIndex ES = NativeCallStackStorage::invalid; // Empty Stack + const SIndex rq = req.callstack; + const int op_index = req.op_to_index(); + const Operation op = req.op(); + assert(op_index >= 0 && op_index < 4, "should be"); + // existing state + SIndex result[4][3] = {// Rl Rs C + {ES, ES, ES}, // op == Release + {ES, ES, ES}, // op == Reserve + {rq, rq, rq}, // op == Commit + {ES, ES, ES} // op == Uncommit + }; + return result[op_index][state_to_index(ex)]; +} + +VMATree::StateType VMATree::get_new_state(const StateType ex, const RequestInfo& req) const { + const StateType Rl = StateType::Released; + const StateType Rs = StateType::Reserved; + const StateType C = StateType::Committed; + const int op = req.op_to_index(); + assert(op >= 0 && op < 4, "should be"); + // existing state + StateType result[4][3] = {// Rl Rs C + {Rl, Rl, Rl}, // op == Release + {Rs, Rs, Rs}, // op == Reserve + { C, C, C}, // op == Commit + {Rl, Rs, Rs} // op == Uncommit + }; + return result[op][state_to_index(ex)]; +} + +MemTag VMATree::get_new_tag(const MemTag ex, const RequestInfo& req) const { + switch(req.op()) { + case Operation::Release: + return mtNone; + case Operation::Reserve: + return req.tag; + case Operation::Commit: + return req.use_tag_inplace ? ex : req.tag; + case Operation::Uncommit: + return ex; + default: + break; + } + return mtNone; +} + +void VMATree::compute_summary_diff(const SingleDiff::delta region_size, + const MemTag current_tag, + const StateType& ex, + const RequestInfo& req, + const MemTag operation_tag, + SummaryDiff& diff) const { + const StateType Rl = StateType::Released; + const StateType Rs = StateType::Reserved; + const StateType C = StateType::Committed; + const int op = req.op_to_index(); + const Operation oper = req.op(); + assert(op >= 0 && op < 4, "should be"); + + SingleDiff::delta a = region_size; + // A region with size `a` has a state as and an operation is requested as in + // The region has tag `current_tag` and the operation has tag `operation_tag`. + // For each state, we decide how much to be added/subtracted from current_tag to operation_tag. Two tables for reserve and commit. + // Each pair of in the table means add `x` to current_tag and add `y` to operation_tag. There are 3 pairs in each row for 3 states. + // For example, `reserve[1][4,5]` says `-a,a` means: + // - we are reserving with operation_tag a region which is already commited with current_tag + // - since we are reserving, then `a` will be added to operation_tag. (`y` is `a`) + // - since we uncommitting (by reserving) then `a` is to be subtracted from current_tag. (`x` is `-a`). + // - amount of uncommitted size is in table `commit[1][4,5]` which is `-a,0` that means subtract `a` from current_tag. + // existing state + SingleDiff::delta reserve[4][3*2] = {// Rl Rs C + {0,0, -a,0, -a,0 }, // op == Release + {0,a, -a,a, -a,a }, // op == Reserve + {0,a, -a,a, -a,a }, // op == Commit + {0,0, 0,0, 0,0 } // op == Uncommit + }; + SingleDiff::delta commit[4][3*2] = {// Rl Rs C + {0,0, 0,0, -a,0 }, // op == Release + {0,0, 0,0, -a,0 }, // op == Reserve + {0,a, 0,a, -a,a }, // op == Commit + {0,0, 0,0, -a,0 } // op == Uncommit + }; + SingleDiff& from_rescom = diff.tag[NMTUtil::tag_to_index(current_tag)]; + SingleDiff& to_rescom = diff.tag[NMTUtil::tag_to_index(operation_tag)]; + int st = state_to_index(ex); + from_rescom.reserve += reserve[op][st * 2 ]; + to_rescom.reserve += reserve[op][st * 2 + 1]; + from_rescom.commit += commit[op][st * 2 ]; + to_rescom.commit += commit[op][st * 2 + 1]; + +} +// update the region state between n1 and n2. Since n1 and n2 are pointers, any update of them will be visible from tree. +// If n1 is noop, it can be removed because its left region (n1->val().in) is already decided and its right state (n1->val().out) is decided here. +// The state of right of n2 (n2->val().out) cannot be decided here yet. +void VMATree::update_region(TreapNode* n1, TreapNode* n2, const RequestInfo& req, SummaryDiff& diff) { + assert(n1 != nullptr,"sanity"); + assert(n2 != nullptr,"sanity"); + //.........n1......n2...... + // ^------^ + // | + IntervalState exSt = n1->val().out; // existing state info + + + StateType existing_state = exSt.type(); + MemTag existing_tag = exSt.mem_tag(); + SIndex existing_reserve_callstack = exSt.reserved_stack(); + SIndex existing_commit_callstack = exSt.committed_stack(); + + StateType new_state = get_new_state(existing_state, req); + MemTag new_tag = get_new_tag(n1->val().out.mem_tag(), req); + SIndex new_reserve_callstack = get_new_reserve_callstack(existing_reserve_callstack, existing_state, req); + SIndex new_commit_callstack = get_new_commit_callstack(existing_commit_callstack, existing_state, req); + + // n1........n2 + // out--> + n1->val().out.set_tag(new_tag); + n1->val().out.set_type(new_state); + n1->val().out.set_reserve_stack(new_reserve_callstack); + n1->val().out.set_commit_stack(new_commit_callstack); + + // n1........n2 + // <--in + n2->val().in.set_tag(new_tag); + n2->val().in.set_type(new_state); + n2->val().in.set_reserve_stack(new_reserve_callstack); + n2->val().in.set_commit_stack(new_commit_callstack); + + SingleDiff::delta region_size = n2->key() - n1->key(); + compute_summary_diff(region_size, existing_tag, existing_state, req, new_tag, diff); +} + +VMATree::SummaryDiff VMATree::register_mapping(position _A, position _B, StateType state, const RegionData& metadata, bool use_tag_inplace) { - assert(!use_tag_inplace || metadata.mem_tag == mtNone, - "If using use_tag_inplace, then the supplied tag should be mtNone, was instead: %s", NMTUtil::tag_to_name(metadata.mem_tag)); - if (A == B) { - // A 0-sized mapping isn't worth recording. + + if (_A == _B) { return SummaryDiff(); } - + assert(_A < _B, "should be"); + SummaryDiff diff; + RequestInfo req{_A, _B, state, metadata.mem_tag, metadata.stack_idx, use_tag_inplace}; IntervalChange stA{ IntervalState{StateType::Released, empty_regiondata}, IntervalState{ state, metadata} @@ -51,176 +258,400 @@ VMATree::SummaryDiff VMATree::register_mapping(position A, position B, StateType IntervalState{ state, metadata}, IntervalState{StateType::Released, empty_regiondata} }; + stA.out.set_commit_stack(NativeCallStackStorage::invalid); + stB.in.set_commit_stack(NativeCallStackStorage::invalid); + VMATreap::Range rA = _tree.find_enclosing_range(_A); + VMATreap::Range rB = _tree.find_enclosing_range(_B); - // First handle A. - // Find closest node that is LEQ A - bool LEQ_A_found = false; - AddressState LEQ_A; - TreapNode* leqA_n = _tree.closest_leq(A); - if (leqA_n == nullptr) { - assert(!use_tag_inplace, "Cannot use the tag inplace if no pre-existing tag exists. From: " PTR_FORMAT " To: " PTR_FORMAT, A, B); - if (use_tag_inplace) { - log_debug(nmt)("Cannot use the tag inplace if no pre-existing tag exists. From: " PTR_FORMAT " To: " PTR_FORMAT, A, B); - } - // No match. We add the A node directly, unless it would have no effect. - if (!stA.is_noop()) { - _tree.upsert(A, stA); + // nodes: .....X.......Y...Z......W........U + // request: A------------------B + // X,Y = enclosing_nodes(A) + // W,U = enclosing_nodes(B) + // The cases are whether or not X and Y exists and X == A. (A == Y doesn't happen since it is searched by 'lt' predicate) + // The cases are whether or not W and U exists and W == B. (B == U doesn't happen since it is searched by 'lt' predicate) + + // We update regions in 3 sections: 1) X..A..Y, 2) Y....W, 3) W..B..U + // Y: is the closest node greater than A, but less than B + // W: is the closest node less than B, but greater than A + // The regions in [Y,W) are updated in a loop. We update X..A..Y before the loop and W..B..U after the loop. + // The table below summarizes the overlap cases. The overlapping case depends on whether X, Y, W and U exist or not, + // and if they exist whether they are the same or not. + // In the notations here, when there is not dot ('.') between two nodes it meaans that they are the same. For example, + // ...XA....Y.... means X == A. + + + // row 0: .........A..................B..... + // row 1: .........A...YW.............B..... // it is impossible, since it means only one node exists in the tree. + // row 2: .........A...Y..........W...B..... + // row 3: .........A...Y.............WB..... + + // row 4: .....X...A..................B..... + // row 5: .....X...A...YW.............B..... + // row 6: .....X...A...Y..........W...B..... + // row 7: .....X...A...Y.............WB..... + + // row 8: ........XA..................B..... + // row 9: ........XA...YW.............B..... + // row 10: ........XA...Y..........W...B..... + // row 11: ........XA...Y.............WB..... + + // row 12: .........A..................B....U + // row 13: .........A...YW.............B....U + // row 14: .........A...Y..........W...B....U + // row 15: .........A...Y.............WB....U + + // row 16: .....X...A..................B....U + // row 17: .....X...A...YW.............B....U + // row 18: .....X...A...Y..........W...B....U + // row 19: .....X...A...Y.............WB....U + + // row 20: ........XA..................B....U + // row 21: ........XA...YW.............B....U + // row 22: ........XA...Y..........W...B....U + // row 23: ........XA...Y.............WB....U + + + // We intentionally did not summarize/compress the cases to keep them as separate. + // This expanded way of describing the cases helps us to understand/analyze/verify/debug/maintain + // the corresponding code more easily. + // Mapping of table to row, row to switch-case should be consistent. If one changes, the others have + // to be updated accordingly. The sequence of dependecies is: table -> row no -> switch(row)-case -> code. + // Meaning that whenever any of one item in this sequence is changed, the rest of the consequent items to + // be checked/changed. + + TreapNode* X = rA.start; + TreapNode* Y = rA.end; + TreapNode* W = rB.start; + TreapNode* U = rB.end; + TreapNode nA{_A, stA, 0}; // the node that represents A + TreapNode nB{_B, stB, 0}; // the node that represents B + TreapNode* A = &nA; + TreapNode* B = &nB; + auto upsert_if= [&](TreapNode* node) { + if (!node->val().is_noop()) { + _tree.upsert(node->key(), node->val()); } - } else { - LEQ_A_found = true; - LEQ_A = AddressState{leqA_n->key(), leqA_n->val()}; - StateType leqA_state = leqA_n->val().out.type(); - StateType new_state = stA.out.type(); - // If we specify use_tag_inplace then the new region takes over the current tag instead of the tag in metadata. - // This is important because the VirtualMemoryTracker API doesn't require supplying the tag for some operations. - if (use_tag_inplace) { - assert(leqA_n->val().out.type() != StateType::Released, "Should not use inplace the tag of a released region"); - MemTag tag = leqA_n->val().out.mem_tag(); - stA.out.set_tag(tag); - stB.in.set_tag(tag); + }; + // update region between n1 and n2 + auto update = [&](TreapNode* n1, TreapNode* n2) { + update_region(n1, n2, req, diff); + }; + auto remove_if = [&](TreapNode* node) -> bool{ + if (node->val().is_noop()) { + _tree.remove(node->key()); + return true; } - - // Unless we know better, let B's outgoing state be the outgoing state of the node at or preceding A. - // Consider the case where the found node is the start of a region enclosing [A,B) - stB.out = out_state(leqA_n); - - // Direct address match. - if (leqA_n->key() == A) { - // Take over in state from old address. - stA.in = in_state(leqA_n); - - // We may now be able to merge two regions: - // If the node's old state matches the new, it becomes a noop. That happens, for example, - // when expanding a committed area: commit [x1, A); ... commit [A, x3) - // and the result should be a larger area, [x1, x3). In that case, the middle node (A and le_n) - // is not needed anymore. So we just remove the old node. - stB.in = stA.out; - if (stA.is_noop()) { - // invalidates leqA_n - _tree.remove(leqA_n->key()); - } else { - // If the state is not matching then we have different operations, such as: - // reserve [x1, A); ... commit [A, x2); or - // reserve [x1, A), mem_tag1; ... reserve [A, x2), mem_tag2; or - // reserve [A, x1), mem_tag1; ... reserve [A, x2), mem_tag2; - // then we re-use the existing out node, overwriting its old metadata. - leqA_n->val() = stA; - } - } else { - // The address must be smaller. - assert(A > leqA_n->key(), "must be"); - - // We add a new node, but only if there would be a state change. If there would not be a - // state change, we just omit the node. - // That happens, for example, when reserving within an already reserved region with identical metadata. - stA.in = out_state(leqA_n); // .. and the region's prior state is the incoming state - if (stA.is_noop()) { - // Nothing to do. - } else { - // Add new node. - _tree.upsert(A, stA); + return false; + }; + GrowableArrayCHeap to_be_removed; + // update regions in [Y,W) + auto update_loop = [&]() { + TreapNode* prev = nullptr; + _tree.visit_range_in_order(_A + 1, _B + 1, [&](TreapNode* curr) { + if (prev != nullptr) { + update_region(prev, curr, req, diff); + // during visit, structure of the tree should not be changed + // keep the keys to be removed, and remove them later + if (prev->val().is_noop()) { + to_be_removed.push(prev->key()); + } } - } - } + prev = curr; + }); + }; + // update region of [A,T) + auto update_A = [&](TreapNode* T) { + A->val().out = A->val().in; + update(A, T); + }; + bool X_exists = X != nullptr; + bool Y_exists = Y != nullptr && Y->key() <= _B; + bool W_exists = W != nullptr && W->key() > _A; + bool U_exists = U != nullptr; + bool X_eq_A = X_exists && X->key() == _A; + bool W_eq_B = W_exists && W->key() == _B; + bool Y_eq_W = Y_exists && W_exists && W->key() == Y->key(); + int row = -1; +#ifdef ASSERT + auto print_case = [&]() { + log_trace(vmatree)(" req: %4d---%4d", (int)_A, (int)_B); + log_trace(vmatree)(" row: %2d", row); + log_trace(vmatree)(" X: %4ld", X_exists ? (long)X->key() : -1); + log_trace(vmatree)(" Y: %4ld", Y_exists ? (long)Y->key() : -1); + log_trace(vmatree)(" W: %4ld", W_exists ? (long)W->key() : -1); + log_trace(vmatree)(" U: %4ld", U_exists ? (long)U->key() : -1); + }; +#endif + // Order of the nodes if they exist are as: X <= A < Y <= W <= B < U + // A---------------------------B + // X Y YW WB U + // XA Y YW WB U + if (!X_exists && !Y_exists && !U_exists) { row = 0; } + if (!X_exists && Y_exists && Y_eq_W && !W_eq_B && !U_exists) { row = 1; } + if (!X_exists && Y_exists && !Y_eq_W && !W_eq_B && !U_exists) { row = 2; } + if (!X_exists && Y_exists && W_eq_B && !U_exists) { row = 3; } - // Now we handle B. - // We first search all nodes that are (A, B]. All of these nodes - // need to be deleted and summary accounted for. The last node before B determines B's outgoing state. - // If there is no node between A and B, its A's incoming state. - GrowableArrayCHeap to_be_deleted_inbetween_a_b; - bool B_needs_insert = true; - - // Find all nodes between (A, B] and record their addresses and values. Also update B's - // outgoing state. - _tree.visit_range_in_order(A + 1, B + 1, [&](TreapNode* head) { - int cmp_B = PositionComparator::cmp(head->key(), B); - stB.out = out_state(head); - if (cmp_B < 0) { - // Record all nodes preceding B. - to_be_deleted_inbetween_a_b.push({head->key(), head->val()}); - } else if (cmp_B == 0) { - // Re-purpose B node, unless it would result in a noop node, in - // which case record old node at B for deletion and summary accounting. - if (stB.is_noop()) { - to_be_deleted_inbetween_a_b.push(AddressState{B, head->val()}); - } else { - head->val() = stB; - } - B_needs_insert = false; - } - }); + if ( X_exists && !Y_exists && !U_exists) { row = 4; } + if ( X_exists && Y_exists && Y_eq_W && !W_eq_B && !U_exists) { row = 5; } + if ( X_exists && Y_exists && !Y_eq_W && !W_eq_B && !U_exists) { row = 6; } + if ( X_exists && Y_exists && W_eq_B && !U_exists) { row = 7; } - // Insert B node if needed - if (B_needs_insert && // Was not already inserted - !stB.is_noop()) // The operation is differing - { - _tree.upsert(B, stB); - } + if ( X_eq_A && !Y_exists && !U_exists) { row = 8; } + if ( X_eq_A && Y_exists && Y_eq_W && !W_eq_B && !U_exists) { row = 9; } + if ( X_eq_A && Y_exists && !Y_eq_W && !W_eq_B && !U_exists) { row = 10; } + if ( X_eq_A && Y_exists && W_eq_B && !U_exists) { row = 11; } - // We now need to: - // a) Delete all nodes between (A, B]. Including B in the case of a noop. - // b) Perform summary accounting - SummaryDiff diff; + if (!X_exists && !Y_exists && U_exists) { row = 12; } + if (!X_exists && Y_exists && Y_eq_W && !W_eq_B && U_exists) { row = 13; } + if (!X_exists && Y_exists && !Y_eq_W && !W_eq_B && U_exists) { row = 14; } + if (!X_exists && Y_exists && W_eq_B && U_exists) { row = 15; } - if (to_be_deleted_inbetween_a_b.length() == 0 && LEQ_A_found) { - // We must have smashed a hole in an existing region (or replaced it entirely). - // LEQ_A < A < B <= C - SingleDiff& rescom = diff.tag[NMTUtil::tag_to_index(LEQ_A.out().mem_tag())]; - if (LEQ_A.out().type() == StateType::Reserved) { - rescom.reserve -= B - A; - } else if (LEQ_A.out().type() == StateType::Committed) { - rescom.commit -= B - A; - rescom.reserve -= B - A; - } - } + if ( X_exists && !Y_exists && U_exists) { row = 16; } + if ( X_exists && Y_exists && Y_eq_W && !W_eq_B && U_exists) { row = 17; } + if ( X_exists && Y_exists && !Y_eq_W && !W_eq_B && U_exists) { row = 18; } + if ( X_exists && Y_exists && W_eq_B && U_exists) { row = 19; } - // Track the previous node. - AddressState prev{A, stA}; - for (int i = 0; i < to_be_deleted_inbetween_a_b.length(); i++) { - const AddressState delete_me = to_be_deleted_inbetween_a_b.at(i); - _tree.remove(delete_me.address); - - // Perform summary accounting - SingleDiff& rescom = diff.tag[NMTUtil::tag_to_index(delete_me.in().mem_tag())]; - if (delete_me.in().type() == StateType::Reserved) { - rescom.reserve -= delete_me.address - prev.address; - } else if (delete_me.in().type() == StateType::Committed) { - rescom.commit -= delete_me.address - prev.address; - rescom.reserve -= delete_me.address - prev.address; - } - prev = delete_me; - } + if ( X_eq_A && !Y_exists && U_exists) { row = 20; } + if ( X_eq_A && Y_exists && Y_eq_W && !W_eq_B && U_exists) { row = 21; } + if ( X_eq_A && Y_exists && !Y_eq_W && !W_eq_B && U_exists) { row = 22; } + if ( X_eq_A && Y_exists && W_eq_B && U_exists) { row = 23; } - if (prev.address != A && prev.out().type() != StateType::Released) { - // The last node wasn't released, so it must be connected to a node outside of (A, B) - // A - prev - B - (some node >= B) - // It might be that prev.address == B == (some node >= B), this is fine. - if (prev.out().type() == StateType::Reserved) { - SingleDiff& rescom = diff.tag[NMTUtil::tag_to_index(prev.out().mem_tag())]; - rescom.reserve -= B - prev.address; - } else if (prev.out().type() == StateType::Committed) { - SingleDiff& rescom = diff.tag[NMTUtil::tag_to_index(prev.out().mem_tag())]; - rescom.commit -= B - prev.address; - rescom.reserve -= B - prev.address; + DEBUG_ONLY(print_case();) + switch(row) { + // row 0: .........A..................B..... + case 0: { + update_A(B); + upsert_if(A); + upsert_if(B); + break; + } + // row 1: .........A...YW.............B..... + case 1: { + ShouldNotReachHere(); + break; + } + // row 2: .........A...Y..........W...B..... + case 2: { + update_A(Y); + upsert_if(A); + update_loop(); + remove_if(Y); + update(W, B); + remove_if(W); + upsert_if(B); + break; + } + // row 3: .........A...Y.............WB..... + case 3: { + update_A(Y); + upsert_if(A); + update_loop(); + remove_if(W); + break; } + // row 4: .....X...A..................B..... + case 4: { + A->val().in = X->val().out; + update_A(B); + upsert_if(A); + upsert_if(B); + break; + } + // row 5: .....X...A...YW.............B..... + case 5: { + A->val().in = X->val().out; + update_A(Y); + upsert_if(A); + update(Y, B); + remove_if(Y); + upsert_if(B); + break; + } + // row 6: .....X...A...Y..........W...B..... + case 6: { + A->val().in = X->val().out; + update_A(Y); + upsert_if(A); + update_loop(); + update(W, B); + remove_if(W); + upsert_if(B); + break; + } + // row 7: .....X...A...Y.............WB..... + case 7: { + A->val().in = X->val().out; + update_A(Y); + upsert_if(A); + update_loop(); + remove_if(W); + break; + } + // row 8: ........XA..................B..... + case 8: { + update(X, B); + remove_if(X); + upsert_if(B); + break; + } + // row 9: ........XA...YW.............B..... + case 9: { + update(X, Y); + remove_if(X); + update(W, B); + remove_if(W); + upsert_if(B); + break; + } + // row 10: ........XA...Y..........W...B..... + case 10: { + update(X, Y); + remove_if(X); + update_loop(); + update(W, B); + remove_if(W); + upsert_if(B); + break; + } + // row 11: ........XA...Y.............WB..... + case 11: { + update(X, Y); + remove_if(X); + update_loop(); + remove_if(W); + break; + } + // row 12: .........A..................B....U + case 12: { + update_A(B); + upsert_if(A); + upsert_if(B); + break; + } + // row 13: .........A...YW.............B....U + case 13: { + update_A(Y); + upsert_if(A); + update(W, B); + remove_if(W); + B->val().out = U->val().in; + upsert_if(B); + break; + } + // row 14: .........A...Y..........W...B....U + case 14: { + update_A(Y); + upsert_if(A); + update_loop(); + update(W, B); + remove_if(W); + B->val().out = U->val().in; + upsert_if(B); + break; + } + // row 15: .........A...Y.............WB....U + case 15: { + update_A(Y); + upsert_if(A); + update_loop(); + remove_if(W); + break; + } + // row 16: .....X...A..................B....U + case 16: { + A->val().in = X->val().out; + update_A(B); + upsert_if(A); + B->val().out = U->val().in; + upsert_if(B); + break; + } + // row 17: .....X...A...YW.............B....U + case 17: { + A->val().in = X->val().out; + update_A(Y); + upsert_if(A); + update(W, B); + remove_if(W); + B->val().out = U->val().in; + upsert_if(B); + break; + } + // row 18: .....X...A...Y..........W...B....U + case 18: { + A->val().in = X->val().out; + update_A(Y); + upsert_if(A); + update_loop(); + update(W, B); + remove_if(W); + B->val().out = U->val().in; + upsert_if(B); + break; + } + // row 19: .....X...A...Y.............WB....U + case 19: { + A->val().in = X->val().out; + update_A(Y); + upsert_if(A); + update_loop(); + remove_if(W); + break; + } + // row 20: ........XA..................B....U + case 20: { + update(X, B); + remove_if(X); + B->val().out = U->val().in; + upsert_if(B); + break; + } + // row 21: ........XA...YW.............B....U + case 21: { + update(X, Y); + remove_if(X); + update(W, B); + remove_if(W); + B->val().out = U->val().in; + upsert_if(B); + break; + } + // row 22: ........XA...Y..........W...B....U + case 22: { + update(X, Y); + remove_if(X); + update_loop(); + update(W, B); + remove_if(W); + B->val().out = U->val().in; + upsert_if(B); + break; + } + // row 23: ........XA...Y.............WB....U + case 23: { + update(X, Y); + remove_if(X); + update_loop(); + remove_if(W); + break; + } + default: + ShouldNotReachHere(); } - // Finally, we can register the new region [A, B)'s summary data. - SingleDiff& rescom = diff.tag[NMTUtil::tag_to_index(stA.out.mem_tag())]; - if (state == StateType::Reserved) { - rescom.reserve += B - A; - } else if (state == StateType::Committed) { - rescom.commit += B - A; - rescom.reserve += B - A; + // Remove the 'noop' nodes that found inside the loop + while(to_be_removed.length() != 0) { + _tree.remove(to_be_removed.pop()); } + return diff; } #ifdef ASSERT void VMATree::print_on(outputStream* out) { visit_in_order([&](TreapNode* current) { - out->print("%zu (%s) - %s - ", current->key(), NMTUtil::tag_to_name(out_state(current).mem_tag()), - statetype_to_string(out_state(current).type())); + out->print("%zu (%s) - %s [%d, %d]-> ", current->key(), NMTUtil::tag_to_name(out_state(current).mem_tag()), + statetype_to_string(out_state(current).type()), current->val().out.reserved_stack(), current->val().out.committed_stack()); }); out->cr(); } @@ -268,7 +699,7 @@ VMATree::SummaryDiff VMATree::set_tag(const position start, const size size, con SummaryDiff diff; // Ignore any released ranges, these must be mtNone and have no stack if (type != StateType::Released) { - RegionData new_data = RegionData(out.stack(), tag); + RegionData new_data = RegionData(out.reserved_stack(), tag); SummaryDiff result = register_mapping(from, end, type, new_data); diff.add(result); } @@ -289,7 +720,7 @@ VMATree::SummaryDiff VMATree::set_tag(const position start, const size size, con StateType type = out.type(); if (type != StateType::Released) { - RegionData new_data = RegionData(out.stack(), tag); + RegionData new_data = RegionData(out.reserved_stack(), tag); SummaryDiff result = register_mapping(from, end, type, new_data); diff.add(result); } diff --git a/src/hotspot/share/nmt/vmatree.hpp b/src/hotspot/share/nmt/vmatree.hpp index 0c639e929b7..d3bf3724c0e 100644 --- a/src/hotspot/share/nmt/vmatree.hpp +++ b/src/hotspot/share/nmt/vmatree.hpp @@ -44,6 +44,7 @@ class VMATree { public: using position = size_t; using size = size_t; + using SIndex = NativeCallStackStorage::StackIndex; class PositionComparator { public: @@ -55,7 +56,7 @@ class VMATree { } }; - enum class StateType : uint8_t { Reserved, Committed, Released, LAST }; + enum class StateType : uint8_t { Released, Reserved, Committed, LAST }; private: static const char* statetype_strings[static_cast(StateType::LAST)]; @@ -70,12 +71,12 @@ class VMATree { // Each point has some stack and a tag associated with it. struct RegionData { - const NativeCallStackStorage::StackIndex stack_idx; + const SIndex stack_idx; const MemTag mem_tag; RegionData() : stack_idx(), mem_tag(mtNone) {} - RegionData(NativeCallStackStorage::StackIndex stack_idx, MemTag mem_tag) + RegionData(SIndex stack_idx, MemTag mem_tag) : stack_idx(stack_idx), mem_tag(mem_tag) {} static bool equals(const RegionData& a, const RegionData& b) { @@ -91,15 +92,27 @@ class VMATree { private: // Store the type and mem_tag as two bytes uint8_t type_tag[2]; - NativeCallStackStorage::StackIndex sidx; + NativeCallStackStorage::StackIndex _reserved_stack; + NativeCallStackStorage::StackIndex _committed_stack; public: - IntervalState() : type_tag{0,0}, sidx() {} + IntervalState() : type_tag{0,0}, _reserved_stack(NativeCallStackStorage::invalid), _committed_stack(NativeCallStackStorage::invalid) {} + IntervalState(const StateType type, + const MemTag mt, + const NativeCallStackStorage::StackIndex res_stack, + const NativeCallStackStorage::StackIndex com_stack) { + assert(!(type == StateType::Released) || mt == mtNone, "Released state-type must have memory tag mtNone"); + type_tag[0] = static_cast(type); + type_tag[1] = static_cast(mt); + _reserved_stack = res_stack; + _committed_stack = com_stack; + } IntervalState(const StateType type, const RegionData data) { assert(!(type == StateType::Released) || data.mem_tag == mtNone, "Released state-type must have memory tag mtNone"); type_tag[0] = static_cast(type); type_tag[1] = static_cast(data.mem_tag); - sidx = data.stack_idx; + _reserved_stack = data.stack_idx; + _committed_stack = NativeCallStackStorage::invalid; } StateType type() const { @@ -110,16 +123,50 @@ class VMATree { return static_cast(type_tag[1]); } - RegionData regiondata() const { - return RegionData{sidx, mem_tag()}; + RegionData reserved_regiondata() const { + return RegionData{_reserved_stack, mem_tag()}; + } + RegionData committed_regiondata() const { + return RegionData{_committed_stack, mem_tag()}; } void set_tag(MemTag tag) { type_tag[1] = static_cast(tag); } - NativeCallStackStorage::StackIndex stack() const { - return sidx; + NativeCallStackStorage::StackIndex reserved_stack() const { + return _reserved_stack; + } + + NativeCallStackStorage::StackIndex committed_stack() const { + return _committed_stack; + } + + void set_reserve_stack(NativeCallStackStorage::StackIndex idx) { + _reserved_stack = idx; + } + + void set_commit_stack(NativeCallStackStorage::StackIndex idx) { + _committed_stack = idx; + } + + bool has_reserved_stack() { + return _reserved_stack != NativeCallStackStorage::invalid; + } + + bool has_committed_stack() { + return _committed_stack != NativeCallStackStorage::invalid; + } + + void set_type(StateType t) { + type_tag[0] = static_cast(t); + } + + bool equals(const IntervalState& other) const { + return mem_tag() == other.mem_tag() && + type() == other.type() && + reserved_stack() == other.reserved_stack() && + committed_stack() == other.committed_stack(); } }; @@ -130,8 +177,14 @@ class VMATree { IntervalState out; bool is_noop() { + if (in.type() == StateType::Released && + in.type() == out.type() && + in.mem_tag() == out.mem_tag()) { + return true; + } return in.type() == out.type() && - RegionData::equals(in.regiondata(), out.regiondata()); + RegionData::equals(in.reserved_regiondata(), out.reserved_regiondata()) && + RegionData::equals(in.committed_regiondata(), out.committed_regiondata()); } }; @@ -193,8 +246,44 @@ class VMATree { #endif }; + enum Operation {Release, Reserve, Commit, Uncommit}; + struct RequestInfo { + position A, B; + StateType _op; + MemTag tag; + SIndex callstack; + bool use_tag_inplace; + Operation op() const { + return + _op == StateType::Reserved && !use_tag_inplace ? Operation::Reserve : + _op == StateType::Committed ? Operation::Commit : + _op == StateType::Reserved && use_tag_inplace ? Operation::Uncommit : + Operation::Release; + } + + int op_to_index() const { + return + _op == StateType::Reserved && !use_tag_inplace ? 1 : + _op == StateType::Committed ? 2 : + _op == StateType::Reserved && use_tag_inplace ? 3 : + 0; + } + }; + private: SummaryDiff register_mapping(position A, position B, StateType state, const RegionData& metadata, bool use_tag_inplace = false); + StateType get_new_state(const StateType existinting_state, const RequestInfo& req) const; + MemTag get_new_tag(const MemTag existinting_tag, const RequestInfo& req) const; + SIndex get_new_reserve_callstack(const SIndex existinting_stack, const StateType ex, const RequestInfo& req) const; + SIndex get_new_commit_callstack(const SIndex existinting_stack, const StateType ex, const RequestInfo& req) const; + void compute_summary_diff(const SingleDiff::delta region_size, const MemTag t1, const StateType& ex, const RequestInfo& req, const MemTag new_tag, SummaryDiff& diff) const; + void update_region(TreapNode* n1, TreapNode* n2, const RequestInfo& req, SummaryDiff& diff); + int state_to_index(const StateType st) const { + return + st == StateType::Released ? 0 : + st == StateType::Reserved ? 1 : + st == StateType::Committed ? 2 : -1; + } public: SummaryDiff reserve_mapping(position from, size size, const RegionData& metadata) { diff --git a/test/hotspot/gtest/nmt/test_vmatree.cpp b/test/hotspot/gtest/nmt/test_vmatree.cpp index 80b5df50062..4d3418cc9fc 100644 --- a/test/hotspot/gtest/nmt/test_vmatree.cpp +++ b/test/hotspot/gtest/nmt/test_vmatree.cpp @@ -36,15 +36,19 @@ using NCS = NativeCallStackStorage; class NMTVMATreeTest : public testing::Test { public: NCS ncs; - constexpr static const int si_len = 2; + constexpr static const int si_len = 4; NCS::StackIndex si[si_len]; NativeCallStack stacks[si_len]; NMTVMATreeTest() : ncs(true) { stacks[0] = make_stack(0xA); stacks[1] = make_stack(0xB); + stacks[2] = make_stack(0xC); + stacks[3] = make_stack(0xD); si[0] = ncs.push(stacks[0]); - si[1] = ncs.push(stacks[0]); + si[1] = ncs.push(stacks[1]); + si[2] = ncs.push(stacks[2]); + si[3] = ncs.push(stacks[3]); } // Utilities @@ -99,6 +103,11 @@ class NMTVMATreeTest : public testing::Test { // Do it backwards instead. Tree tree2; + // 900---1000 + // 800--900 + // 700--800 + // ... + // 0--100 for (int i = 9; i >= 0; i--) { tree2.reserve_mapping(i * 100, 100, rd); } @@ -167,6 +176,164 @@ class NMTVMATreeTest : public testing::Test { EXPECT_TRUE(exists(found[2])); EXPECT_TRUE(exists(found[3])); }; + template struct ExpectedTree { + int nodes[NodeCount]; + MemTag tags[NodeCount + 1]; + VMATree::StateType states[NodeCount + 1]; + NativeCallStackStorage::StackIndex res_si[NodeCount + 1]; + NativeCallStackStorage::StackIndex com_si[NodeCount + 1]; + }; + + using State = VMATree::StateType; + using SIndex = VMATree::SIndex; + + struct UpdateCallInfo { + VMATree::IntervalState ex_st; + VMATree::RequestInfo req; + VMATree::IntervalState new_st; + int reserve[2], commit[2]; + }; + + void call_update_region(const UpdateCallInfo upd) { + VMATree::TreapNode n1{upd.req.A, {}, 0}, n2{upd.req.B, {}, 0}; + n1.val().out= upd.ex_st; + n2.val().in = n1.val().out; + Tree tree; + VMATree::SummaryDiff diff; + tree.update_region(&n1, &n2, upd.req, diff); + int from = NMTUtil::tag_to_index(upd.ex_st.mem_tag()); + int to = NMTUtil::tag_to_index(upd.new_st.mem_tag()); + stringStream ss; + ss.print("Ex. State: %d, op: %d, use-tag:%d, from==to: %d", + (int)upd.ex_st.type(), (int)upd.req.op_to_index(), upd.req.use_tag_inplace, from == to); + const char* failed_case = ss.base(); + EXPECT_EQ(n1.val().out.type(), upd.new_st.type()) << failed_case; + EXPECT_EQ(n1.val().out.mem_tag(), upd.new_st.mem_tag()) << failed_case; + EXPECT_EQ(n1.val().out.reserved_stack(), upd.new_st.reserved_stack()) << failed_case; + EXPECT_EQ(n1.val().out.committed_stack(), upd.new_st.committed_stack()) << failed_case; + + if (from == to) { + EXPECT_EQ(diff.tag[from].reserve, upd.reserve[0] + upd.reserve[1]) << failed_case; + EXPECT_EQ(diff.tag[from].commit, upd.commit[0] + upd.commit[1]) << failed_case; + } else { + EXPECT_EQ(diff.tag[from].reserve, upd.reserve[0]) << failed_case; + EXPECT_EQ(diff.tag[from].commit, upd.commit[0]) << failed_case; + EXPECT_EQ(diff.tag[to].reserve, upd.reserve[1]) << failed_case; + EXPECT_EQ(diff.tag[to].commit, upd.commit[1]) << failed_case; + } + } + + template + void create_tree(Tree& tree, ExpectedTree& et, int line_no) { + using SIndex = NativeCallStackStorage::StackIndex; + const SIndex ES = NativeCallStackStorage::invalid; // Empty Stack + VMATree::IntervalChange st; + for (int i = 0; i < N; i++) { + st.in.set_type(et.states[i]); + st.in.set_tag(et.tags[i]); + if (et.res_si[i] >= 0) { + st.in.set_reserve_stack(et.res_si[i]); + } else { + st.in.set_reserve_stack(ES); + } + if (et.com_si[i] >= 0) { + st.in.set_commit_stack(et.com_si[i]); + } else { + st.in.set_commit_stack(ES); + } + + st.out.set_type(et.states[i+1]); + st.out.set_tag(et.tags[i+1]); + if (et.res_si[i+1] >= 0) { + st.out.set_reserve_stack(et.res_si[i+1]); + } else { + st.out.set_reserve_stack(ES); + } + if (et.com_si[i+1] >= 0) { + st.out.set_commit_stack(et.com_si[i+1]); + } else { + st.out.set_commit_stack(ES); + } + tree.tree().upsert((VMATree::position)et.nodes[i], st); + } + print_tree(et, line_no); +} + + template + void check_tree(Tree& tree, const ExpectedTree& et, int line_no) { + using Node = VMATree::TreapNode; + auto left_released = [&](Node n) -> bool { + return n.val().in.type() == VMATree::StateType::Released and + n.val().in.mem_tag() == mtNone; + }; + auto right_released = [&](Node n) -> bool { + return n.val().out.type() == VMATree::StateType::Released and + n.val().out.mem_tag() == mtNone; + }; + for (int i = 0; i < N; i++) { + VMATree::VMATreap::Range r = tree.tree().find_enclosing_range(et.nodes[i]); + ASSERT_TRUE(r.start != nullptr); + Node node = *r.start; + ASSERT_EQ(node.key(), (VMATree::position)et.nodes[i]) << "at line " << line_no; + if (i == (N -1)) { // last node + EXPECT_TRUE(right_released(node)) << "right-of last node is not Released"; + break; + } + if (i == 0) { // first node + EXPECT_TRUE(left_released(node)) << "left-of first node is not Released"; + } + stringStream ss(50); + ss.print("test at line: %d, for node: %d", line_no, et.nodes[i]); + const char* for_this_node = ss.base(); + EXPECT_EQ(node.val().out.type(), et.states[i+1]) << for_this_node; + EXPECT_EQ(node.val().out.mem_tag(), et.tags[i+1]) << for_this_node; + if (et.res_si[i+1] >= 0) { + EXPECT_EQ(node.val().out.reserved_stack(), et.res_si[i+1]) << for_this_node; + EXPECT_EQ(r.end->val().in.reserved_stack(), et.res_si[i+1]) << for_this_node; + } else { + EXPECT_FALSE(node.val().out.has_reserved_stack()) << for_this_node; + EXPECT_FALSE(r.end->val().in.has_reserved_stack()) << for_this_node; + } + if (et.com_si[i+1] >= 0) { + EXPECT_EQ(node.val().out.committed_stack(), et.com_si[i+1]) << for_this_node; + EXPECT_EQ(r.end->val().in.committed_stack(), et.com_si[i+1]) << for_this_node; + } else { + EXPECT_FALSE(node.val().out.has_committed_stack()) << for_this_node; + EXPECT_FALSE(r.end->val().in.has_committed_stack()) << for_this_node; + } + } + print_tree(et, line_no); + } + + template + void print_tree(const ExpectedTree& et, int line_no) { + const State Rs = State::Reserved; + const State Rl = State::Released; + const State C = State::Committed; + stringStream ss; + ss.print_cr("Tree nodes for line %d", line_no); + ss.print_cr(" // 1 2 3 4 5"); + ss.print_cr(" // 012345678901234567890123456789012345678901234567890"); + ss.print (" // "); + int j = 0; + for (int i = 0; i < N; i++) { + char state_char = et.states[i+1] == Rl ? '.' : + et.states[i+1] == Rs ? 'r' : + et.states[i+1] == C ? 'C' : ' '; + if (i == 0 && et.nodes[i] != 0) { + for (j = 0; j < et.nodes[i]; j++) { + ss.put('.'); + } + } + for (j = et.nodes[i]; i < (N - 1) && j < et.nodes[i + 1]; j++) { + ss.put(state_char); + } + } + for (; j <= 50; j++) { + ss.put('.'); + } + tty->print_cr("%s", ss.base()); + } }; @@ -179,13 +346,17 @@ TEST_VM_F(NMTVMATreeTest, OverlappingReservationsResultInTwoNodes) { EXPECT_EQ(2, count_nodes(tree)); } -TEST_VM_F(NMTVMATreeTest, UseFlagInplace) { +TEST_VM_F(NMTVMATreeTest, UseTagInplace) { Tree tree; - VMATree::RegionData rd1(si[0], mtTest); - VMATree::RegionData rd2(si[1], mtNone); - tree.reserve_mapping(0, 100, rd1); - tree.commit_mapping(20, 50, rd2, true); - tree.uncommit_mapping(30, 10, rd2); + VMATree::RegionData rd_Test_cs0(si[0], mtTest); + VMATree::RegionData rd_None_cs1(si[1], mtNone); + tree.reserve_mapping(0, 100, rd_Test_cs0); + // reserve: 0---------------------100 + // commit: 20**********70 + // uncommit: 30--40 + // post-cond: 0---20**30--40**70----100 + tree.commit_mapping(20, 50, rd_None_cs1, true); + tree.uncommit_mapping(30, 10, rd_None_cs1); tree.visit_in_order([&](TNode* node) { if (node->key() != 100) { EXPECT_EQ(mtTest, node->val().out.mem_tag()) << "failed at: " << node->key(); @@ -211,10 +382,10 @@ TEST_VM_F(NMTVMATreeTest, LowLevel) { { // Identical operation but different metadata should not merge Tree tree; - VMATree::RegionData rd{si[0], mtTest }; - VMATree::RegionData rd2{si[1], mtNMT }; - tree.reserve_mapping(0, 100, rd); - tree.reserve_mapping(100, 100, rd2); + VMATree::RegionData rd_Test_cs0{si[0], mtTest}; + VMATree::RegionData rd_NMT_cs1{si[1], mtNMT}; + tree.reserve_mapping(0, 100, rd_Test_cs0); + tree.reserve_mapping(100, 100, rd_NMT_cs1); EXPECT_EQ(3, count_nodes(tree)); int found_nodes = 0; @@ -222,14 +393,14 @@ TEST_VM_F(NMTVMATreeTest, LowLevel) { { // Reserving after commit should overwrite commit Tree tree; - VMATree::RegionData rd{si[0], mtTest }; - VMATree::RegionData rd2{si[1], mtNMT }; - tree.commit_mapping(50, 50, rd2); - tree.reserve_mapping(0, 100, rd); + VMATree::RegionData rd_Test_cs0{si[0], mtTest}; + VMATree::RegionData rd_NMT_cs1{si[1], mtNMT}; + tree.commit_mapping(50, 50, rd_NMT_cs1); + tree.reserve_mapping(0, 100, rd_Test_cs0); treap(tree).visit_in_order([&](TNode* x) { EXPECT_TRUE(x->key() == 0 || x->key() == 100); if (x->key() == 0) { - EXPECT_EQ(x->val().out.regiondata().mem_tag, mtTest); + EXPECT_EQ(x->val().out.reserved_regiondata().mem_tag, mtTest); } }); @@ -238,19 +409,19 @@ TEST_VM_F(NMTVMATreeTest, LowLevel) { { // Split a reserved region into two different reserved regions Tree tree; - VMATree::RegionData rd{si[0], mtTest }; - VMATree::RegionData rd2{si[1], mtNMT }; - VMATree::RegionData rd3{si[0], mtNone }; - tree.reserve_mapping(0, 100, rd); - tree.reserve_mapping(0, 50, rd2); - tree.reserve_mapping(50, 50, rd3); + VMATree::RegionData rd_Test_cs0{si[0], mtTest}; + VMATree::RegionData rd_NMT_cs1{si[1], mtNMT}; + VMATree::RegionData rd_None_cs0{si[0], mtNone}; + tree.reserve_mapping(0, 100, rd_Test_cs0); + tree.reserve_mapping(0, 50, rd_NMT_cs1); + tree.reserve_mapping(50, 50, rd_None_cs0); EXPECT_EQ(3, count_nodes(tree)); } { // One big reserve + release leaves an empty tree - Tree::RegionData rd{si[0], mtNMT}; + VMATree::RegionData rd_NMT_cs0{si[0], mtNMT}; Tree tree; - tree.reserve_mapping(0, 500000, rd); + tree.reserve_mapping(0, 500000, rd_NMT_cs0); tree.release_mapping(0, 500000); EXPECT_EQ(nullptr, treap_root(tree)); @@ -258,27 +429,27 @@ TEST_VM_F(NMTVMATreeTest, LowLevel) { { // A committed region inside of/replacing a reserved region // should replace the reserved region's metadata. - Tree::RegionData rd{si[0], mtNMT}; - VMATree::RegionData rd2{si[1], mtTest}; + VMATree::RegionData rd_NMT_cs0{si[0], mtNMT}; + VMATree::RegionData rd_Test_cs1{si[1], mtTest}; Tree tree; - tree.reserve_mapping(0, 100, rd); - tree.commit_mapping(0, 100, rd2); + tree.reserve_mapping(0, 100, rd_NMT_cs0); + tree.commit_mapping(0, 100, rd_Test_cs1); treap(tree).visit_range_in_order(0, 99999, [&](TNode* x) { if (x->key() == 0) { - EXPECT_EQ(mtTest, x->val().out.regiondata().mem_tag); + EXPECT_EQ(mtTest, x->val().out.reserved_regiondata().mem_tag); } if (x->key() == 100) { - EXPECT_EQ(mtTest, x->val().in.regiondata().mem_tag); + EXPECT_EQ(mtTest, x->val().in.reserved_regiondata().mem_tag); } }); } { // Attempting to reserve or commit an empty region should not change the tree. Tree tree; - Tree::RegionData rd{si[0], mtNMT}; - tree.reserve_mapping(0, 0, rd); + VMATree::RegionData rd_NMT_cs0{si[0], mtNMT}; + tree.reserve_mapping(0, 0, rd_NMT_cs0); EXPECT_EQ(nullptr, treap_root(tree)); - tree.commit_mapping(0, 0, rd); + tree.commit_mapping(0, 0, rd_NMT_cs0); EXPECT_EQ(nullptr, treap_root(tree)); } } @@ -289,12 +460,12 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { VMATree::position from; VMATree::position to; MemTag tag; - NCS::StackIndex stack; + NCS::StackIndex reserve_stack; State state; }; // Take a sorted list of testranges and check that those and only those are found in the tree. - auto expect_equivalent_form = [&](auto& expected, VMATree& tree) { + auto expect_equivalent_form = [&](auto& expected, VMATree& tree, int line_no) { // With auto& our arrays do not deteriorate to pointers but are kept as testrange[N] // so this actually works! int len = sizeof(expected) / sizeof(testrange); @@ -311,11 +482,11 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { EXPECT_EQ(expect.from, found.start->key()); EXPECT_EQ(expect.to, found.end->key()); // Same tag - EXPECT_EQ(expect.tag, found.start->val().out.mem_tag()); - EXPECT_EQ(expect.tag, found.end->val().in.mem_tag()); + EXPECT_EQ(expect.tag, found.start->val().out.mem_tag()) << " and at test-line: " << line_no; + EXPECT_EQ(expect.tag, found.end->val().in.mem_tag()) << " and at test-line: " << line_no; // Same stack - EXPECT_EQ(expect.stack, found.start->val().out.stack()); - EXPECT_EQ(expect.stack, found.end->val().in.stack()); + EXPECT_EQ(expect.reserve_stack, found.start->val().out.reserved_stack()) << "Unexpected stack at region: " << i << " and at test-line: " << line_no; + EXPECT_EQ(expect.reserve_stack, found.end->val().in.reserved_stack()) << "Unexpected stack at region: " << i << " and at test-line: " << line_no; // Same state EXPECT_EQ(expect.state, found.start->val().out.type()); EXPECT_EQ(expect.state, found.end->val().in.type()); @@ -324,6 +495,8 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { EXPECT_EQ(len+1, tree.tree().size()); }; NCS::StackIndex si = NCS::StackIndex(); + NCS::StackIndex es = NCS::invalid; // empty or no stack is stored + Tree::RegionData rd(si, mtNone); { // The gc/cds case with only reserved data @@ -337,7 +510,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { tree.set_tag(0, 500, mtGC); tree.set_tag(500, 100, mtClassShared); - expect_equivalent_form(expected, tree); + expect_equivalent_form(expected, tree, __LINE__); } { // Now let's add in some committed data @@ -353,6 +526,13 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { }; VMATree tree; + // 0---------------------------------------------------600 + // 100****225 + // 550***560 + // 565***575 + // 0------100****225---------550***560---565***575-----600 + // 0------100****225---500---550***560---565***575-----600 + // <-------mtGC---------><-----------mtClassShared-------> tree.reserve_mapping(0, 600, rd); // The committed areas tree.commit_mapping(100, 125, rd); @@ -361,7 +541,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { // OK, set tag tree.set_tag(0, 500, mtGC); tree.set_tag(500, 100, mtClassShared); - expect_equivalent_form(expected, tree); + expect_equivalent_form(expected, tree, __LINE__); } { // Setting the tag for adjacent regions with same stacks should merge the regions @@ -374,7 +554,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { tree.reserve_mapping(0, 100, gc); tree.reserve_mapping(100, 100, compiler); tree.set_tag(0, 200, mtGC); - expect_equivalent_form(expected, tree); + expect_equivalent_form(expected, tree, __LINE__); } { // Setting the tag for adjacent regions with different stacks should NOT merge the regions @@ -390,7 +570,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { tree.reserve_mapping(0, 100, gc); tree.reserve_mapping(100, 100, compiler); tree.set_tag(0, 200, mtGC); - expect_equivalent_form(expected, tree); + expect_equivalent_form(expected, tree, __LINE__); } { // Setting the tag in the middle of a range causes a split @@ -403,7 +583,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { Tree::RegionData compiler(si, mtCompiler); tree.reserve_mapping(0, 200, compiler); tree.set_tag(100, 50, mtGC); - expect_equivalent_form(expected, tree); + expect_equivalent_form(expected, tree, __LINE__); } { // Setting the tag in between two ranges causes a split @@ -418,13 +598,13 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { tree.reserve_mapping(0, 100, gc); tree.reserve_mapping(100, 100, compiler); tree.set_tag(75, 50, mtClass); - expect_equivalent_form(expected, tree); + expect_equivalent_form(expected, tree, __LINE__); } { // Holes in the address range are acceptable and untouched testrange expected[]{ { 0, 50, mtGC, si, State::Reserved}, - {50, 75, mtNone, si, State::Released}, + {50, 75, mtNone, es, State::Released}, {75, 80, mtGC, si, State::Reserved}, {80, 100, mtClassShared, si, State::Reserved} }; @@ -433,7 +613,7 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { tree.reserve_mapping(0, 50, class_shared); tree.reserve_mapping(75, 25, class_shared); tree.set_tag(0, 80, mtGC); - expect_equivalent_form(expected, tree); + expect_equivalent_form(expected, tree, __LINE__); } { // Check that setting tag with 'hole' not consisting of any regions work @@ -444,15 +624,15 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { Tree::RegionData class_shared(si, mtClassShared); tree.reserve_mapping(10, 10, class_shared); tree.set_tag(0, 100, mtCompiler); - expect_equivalent_form(expected, tree); + expect_equivalent_form(expected, tree, __LINE__); } { // Check that multiple holes still work testrange expected[]{ { 0, 1, mtGC, si, State::Reserved}, - { 1, 50, mtNone, si, State::Released}, + { 1, 50, mtNone, es, State::Released}, {50, 75, mtGC, si, State::Reserved}, - {75, 99, mtNone, si, State::Released}, + {75, 99, mtNone, es, State::Released}, {99, 100, mtGC, si, State::Reserved} }; VMATree tree; @@ -461,79 +641,158 @@ TEST_VM_F(NMTVMATreeTest, SetTag) { tree.release_mapping(1, 49); tree.release_mapping(75, 24); tree.set_tag(0, 100, mtGC); - expect_equivalent_form(expected, tree); + expect_equivalent_form(expected, tree, __LINE__); } } // Tests for summary accounting TEST_VM_F(NMTVMATreeTest, SummaryAccounting) { { // Fully enclosed re-reserving works correctly. - Tree::RegionData rd(NCS::StackIndex(), mtTest); - Tree::RegionData rd2(NCS::StackIndex(), mtNMT); + Tree::RegionData rd_Test_cs0(NCS::StackIndex(), mtTest); + Tree::RegionData rd_NMT_cs0(NCS::StackIndex(), mtNMT); Tree tree; - VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 100, rd); + VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 100, rd_Test_cs0); +// 1 2 3 4 5 6 7 8 9 10 11 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.......... +// Legend: +// A - Test (reserved) +// . - free VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; EXPECT_EQ(100, diff.reserve); - all_diff = tree.reserve_mapping(50, 25, rd2); + all_diff = tree.reserve_mapping(50, 25, rd_NMT_cs0); +// 1 2 3 4 5 6 7 8 9 10 11 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCC.......... +// Legend: +// A - Test (reserved) +// B - Native Memory Tracking (reserved) +// C - Test (reserved) +// . - free diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; VMATree::SingleDiff diff2 = all_diff.tag[NMTUtil::tag_to_index(mtNMT)]; EXPECT_EQ(-25, diff.reserve); EXPECT_EQ(25, diff2.reserve); } { // Fully release reserved mapping - Tree::RegionData rd(NCS::StackIndex(), mtTest); + Tree::RegionData rd_Test_cs0(NCS::StackIndex(), mtTest); Tree tree; - VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 100, rd); + VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 100, rd_Test_cs0); +// 1 2 3 4 5 6 7 8 9 10 11 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.......... +// Legend: +// A - Test (reserved) +// . - free VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; EXPECT_EQ(100, diff.reserve); all_diff = tree.release_mapping(0, 100); +// 1 2 3 4 5 6 7 8 9 10 11 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +// .............................................................................................................. +// Legend: diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; EXPECT_EQ(-100, diff.reserve); } { // Convert some of a released mapping to a committed one - Tree::RegionData rd(NCS::StackIndex(), mtTest); + Tree::RegionData rd_Test_cs0(NCS::StackIndex(), mtTest); Tree tree; - VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 100, rd); + VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 100, rd_Test_cs0); +// 1 2 3 4 5 6 7 8 9 10 11 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +// AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.......... +// Legend: +// A - Test (reserved) +// . - free VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; EXPECT_EQ(diff.reserve, 100); - all_diff = tree.commit_mapping(0, 100, rd); + all_diff = tree.commit_mapping(0, 100, rd_Test_cs0); +// 1 2 3 4 5 6 7 8 9 10 11 +// 01234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789 +// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......... +// Legend: +// a - Test (committed) +// . - free diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; EXPECT_EQ(0, diff.reserve); EXPECT_EQ(100, diff.commit); } { // Adjacent reserved mappings with same type - Tree::RegionData rd(NCS::StackIndex(), mtTest); + Tree::RegionData rd_Test_cs0(NCS::StackIndex(), mtTest); Tree tree; - VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 100, rd); + VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 10, rd_Test_cs0); +// 1 2 +// 01234567890123456789 +// AAAAAAAAAA.......... +// Legend: +// A - Test (reserved) +// . - free VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; - EXPECT_EQ(diff.reserve, 100); - all_diff = tree.reserve_mapping(100, 100, rd); + EXPECT_EQ(diff.reserve, 10); + all_diff = tree.reserve_mapping(10, 10, rd_Test_cs0); +// 1 2 3 +// 012345678901234567890123456789 +// AAAAAAAAAAAAAAAAAAAA.......... +// Legend: +// A - Test (reserved) +// . - free diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; - EXPECT_EQ(100, diff.reserve); + EXPECT_EQ(10, diff.reserve); } { // Adjacent reserved mappings with different tags - Tree::RegionData rd(NCS::StackIndex(), mtTest); - Tree::RegionData rd2(NCS::StackIndex(), mtNMT); + Tree::RegionData rd_Test_cs0(NCS::StackIndex(), mtTest); + Tree::RegionData rd_NMT_cs0(NCS::StackIndex(), mtNMT); Tree tree; - VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 100, rd); + VMATree::SummaryDiff all_diff = tree.reserve_mapping(0, 10, rd_Test_cs0); +// 1 2 +// 01234567890123456789 +// AAAAAAAAAA.......... +// Legend: +// A - Test (reserved) +// . - free VMATree::SingleDiff diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; - EXPECT_EQ(diff.reserve, 100); - all_diff = tree.reserve_mapping(100, 100, rd2); + EXPECT_EQ(diff.reserve, 10); + all_diff = tree.reserve_mapping(10, 10, rd_NMT_cs0); +// 1 2 3 +// 012345678901234567890123456789 +// AAAAAAAAAABBBBBBBBBB.......... +// Legend: +// A - Test (reserved) +// B - Native Memory Tracking (reserved) +// . - free diff = all_diff.tag[NMTUtil::tag_to_index(mtTest)]; EXPECT_EQ(0, diff.reserve); diff = all_diff.tag[NMTUtil::tag_to_index(mtNMT)]; - EXPECT_EQ(100, diff.reserve); + EXPECT_EQ(10, diff.reserve); } { // A commit with two previous commits inside of it should only register // the new memory in the commit diff. Tree tree; - Tree::RegionData rd(NCS::StackIndex(), mtTest); - tree.commit_mapping(128, 128, rd); - tree.commit_mapping(512, 128, rd); - VMATree::SummaryDiff diff = tree.commit_mapping(0, 1024, rd); - EXPECT_EQ(768, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); - EXPECT_EQ(768, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + Tree::RegionData rd_Test_cs0(NCS::StackIndex(), mtTest); + tree.commit_mapping(16, 16, rd_Test_cs0); +// 1 2 3 4 +// 0123456789012345678901234567890123456789 +// ................aaaaaaaaaaaaaaaa.......... +// Legend: +// a - Test (committed) +// . - free + tree.commit_mapping(32, 32, rd_Test_cs0); +// 1 2 3 4 5 6 7 +// 0123456789012345678901234567890123456789012345678901234567890123456789 +// ................aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......... +// Legend: +// a - Test (committed) +// . - free + VMATree::SummaryDiff diff = tree.commit_mapping(0, 64, rd_Test_cs0); +// 1 2 3 4 5 6 7 +// 0123456789012345678901234567890123456789012345678901234567890123456789 +// aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.......... +// Legend: +// a - Test (committed) +// . - free + EXPECT_EQ(16, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); + EXPECT_EQ(16, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); } } @@ -713,10 +972,21 @@ TEST_VM_F(NMTVMATreeTest, TestConsistencyWithSimpleTracker) { VMATree::TreapNode* endn = find(treap, (end * page_size) + page_size); ASSERT_NE(nullptr, endn); - const NativeCallStack& start_stack = ncss.get(startn->val().out.stack()); - const NativeCallStack& end_stack = ncss.get(endn->val().in.stack()); - ASSERT_TRUE(starti.stack.equals(start_stack)); - ASSERT_TRUE(endi.stack.equals(end_stack)); + const NativeCallStack& start_stack = ncss.get(startn->val().out.reserved_stack()); + const NativeCallStack& end_stack = ncss.get(endn->val().in.reserved_stack()); + // If start-node of a reserved region is committed, the stack is stored in the second_stack of the node. + if (startn->val().out.has_committed_stack()) { + const NativeCallStack& start_second_stack = ncss.get(startn->val().out.committed_stack()); + ASSERT_TRUE(starti.stack.equals(start_stack) || starti.stack.equals(start_second_stack)); + } else { + ASSERT_TRUE(starti.stack.equals(start_stack)); + } + if (endn->val().in.has_committed_stack()) { + const NativeCallStack& end_second_stack = ncss.get(endn->val().in.committed_stack()); + ASSERT_TRUE(endi.stack.equals(end_stack) || endi.stack.equals(end_second_stack)); + } else { + ASSERT_TRUE(endi.stack.equals(end_stack)); + } ASSERT_EQ(starti.mem_tag, startn->val().out.mem_tag()); ASSERT_EQ(endi.mem_tag, endn->val().in.mem_tag()); @@ -725,18 +995,994 @@ TEST_VM_F(NMTVMATreeTest, TestConsistencyWithSimpleTracker) { } } -TEST_VM_F(NMTVMATreeTest, SummaryAccountingWhenUseFlagInplace) { +TEST_VM_F(NMTVMATreeTest, SummaryAccountingWhenUseTagInplace) { Tree tree; - VMATree::RegionData rd1(si[0], mtTest); - VMATree::RegionData rd2(si[1], mtNone); - tree.reserve_mapping(0, 100, rd1); - VMATree::SummaryDiff diff = tree.commit_mapping(0, 50, rd2, true); + VMATree::RegionData rd_Test_cs0(si[0], mtTest); + VMATree::RegionData rd_None_cs1(si[1], mtNone); +// 1 2 3 4 5 +// 012345678901234567890123456789012345678901234567890 +// .................................................. + tree.reserve_mapping(0, 50, rd_Test_cs0); +// 1 2 3 4 5 +// 012345678901234567890123456789012345678901234567890 +// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr +VMATree::SummaryDiff diff = tree.commit_mapping(0, 25, rd_None_cs1, true); +// 1 2 3 4 5 +// 012345678901234567890123456789012345678901234567890 +// CCCCCCCCCCCCCCCCCCCCCCCCCrrrrrrrrrrrrrrrrrrrrrrrrr EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); - EXPECT_EQ(50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); - diff = tree.commit_mapping(60, 10, rd2, true); + EXPECT_EQ(25, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); + + diff = tree.commit_mapping(30, 5, rd_None_cs1, true); +// 1 2 3 4 5 +// 012345678901234567890123456789012345678901234567890 +// CCCCCCCCCCCCCCCCCCCCCCCCCrrrrrCCCCCrrrrrrrrrrrrrrr EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); - EXPECT_EQ(10, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); - diff = tree.uncommit_mapping(0, 50, rd2); + EXPECT_EQ(5, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); + + diff = tree.uncommit_mapping(0, 25, rd_None_cs1); +// 1 2 3 4 5 +// 012345678901234567890123456789012345678901234567890 +// rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrCCCCCrrrrrrrrrrrrrrr EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); - EXPECT_EQ(-50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); + EXPECT_EQ(-25, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); +} + +// How the memory regions are visualized: +// 1 2 3 4 5 6 7 | +// 0123456789012345678901234567890123456789012345678901234567890123456789 |_> memory address +// aaaaaaBBBBBBBcccccccDDDDDDDeeeeeeeFFFFFFFF........................... |->some letters showing the state of the memory +// Legend: +// . - None (free/released) +// r - MemTag (reserved) +// C - MemTag (committed) +// MemTag is Test if omitted. + +TEST_VM_F(NMTVMATreeTest, SeparateStacksForCommitAndReserve) { + using SIndex = NativeCallStackStorage::StackIndex; + using State = VMATree::StateType; + SIndex si_1 = si[0]; + SIndex si_2 = si[1]; + + const State Rs = State::Reserved; + const State Rl = State::Released; + const State C = State::Committed; + VMATree::RegionData rd_Test_cs1(si_1, mtTest); + VMATree::RegionData rd_None_cs2(si_2, mtNone); + + {// Check committing into a reserved region inherits the call stacks + Tree tree; + tree.reserve_mapping(0, 50, rd_Test_cs1); // reserve in an empty tree + // Pre: empty tree. + // Post: + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr. + ExpectedTree<2> et1 = {{ 0, 50 }, + {mtNone, mtTest, mtNone}, + {Rl , Rs , Rl }, + {-1 , si_1 , -1 }, + {-1 , -1 , -1 }}; + check_tree(tree, et1, __LINE__); + tree.commit_mapping(25, 10, rd_None_cs2, true); // commit at the middle of the region + // Post: + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrrrrrrrrrrrrrrrrrCCCCCCCCCCrrrrrrrrrrrrrrr. + ExpectedTree<4> et2 = {{ 0, 25, 35, 50 }, + {mtNone, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , C , Rs , Rl }, + {-1 , si_1 , si_1 , si_1 , -1 }, + {-1 , -1 , si_2 , -1 , -1 }}; + check_tree(tree, et2, __LINE__); + + tree.commit_mapping(0, 20, rd_None_cs2, true); // commit at the beginning of the region + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // CCCCCCCCCCCCCCCCCCCCrrrrrCCCCCCCCCCrrrrrrrrrrrrrrr. + ExpectedTree<5> et3 = {{ 0, 20, 25, 35, 50 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , C , Rs , C , Rs , Rl }, + {-1 , si_1 , si_1 , si_1 , si_1 , -1 }, + {-1 , si_2 , -1 , si_2 , -1 , -1 }}; + check_tree(tree, et3, __LINE__); + + tree.commit_mapping(40, 10, rd_None_cs2, true); // commit at the end of the region + // Post: + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // CCCCCCCCCCCCCCCCCCCCrrrrrCCCCCCCCCCrrrrrCCCCCCCCCC. + ExpectedTree<6> et4 = {{ 0, 20, 25, 35, 40, 50 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , C , Rs , C , Rs , C , Rl }, + {-1 , si_1 , si_1 , si_1 , si_1 , si_1 , -1 }, + {-1 , si_2 , -1 , si_2 , -1 , si_2 , -1 }}; + check_tree(tree, et4, __LINE__); + } + {// committing overlapped regions does not destroy the old call-stacks + Tree tree; + tree.reserve_mapping(0, 50, rd_Test_cs1); // reserving in an empty tree + // Pre: empty tree. + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr + ExpectedTree<2> et1 = {{ 0 , 50 }, + {mtNone, mtTest, mtNone}, + {Rl , Rs , Rl }, + {-1 , si_1 , -1 }, + {-1 , -1 , -1 }}; + check_tree(tree, et1, __LINE__); + + tree.commit_mapping(10, 10, rd_None_cs2, true); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrrCCCCCCCCCCrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr + ExpectedTree<4> et2 = {{ 0, 10, 20, 50 }, + {mtNone, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , C , Rs , Rl }, + {-1 , si_1 , si_1 , si_1 , -1 }, + {-1 , -1 , si_2 , -1 , -1 }}; + check_tree(tree, et2, __LINE__); + + SIndex si_3 = si[2]; + VMATree::RegionData rd_Test_cs3(si_3, mtTest); + // commit with overlap at the region's start + tree.commit_mapping(5, 10, rd_Test_cs3); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrCCCCCCCCCCCCCCCrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr + ExpectedTree<5> et3 = {{ 0, 5, 15, 20, 50 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , C , C , Rs , Rl }, + {-1 , si_1 , si_1 , si_1 , si_1 , -1 }, + {-1 , -1 , si_3 , si_2 , -1 , -1 }}; + check_tree(tree, et3, __LINE__); + + SIndex si_4 = si[3]; + VMATree::RegionData call_stack_4(si_4, mtTest); + // commit with overlap at the region's end + tree.commit_mapping(15, 10, call_stack_4); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrCCCCCCCCCCCCCCCCCCCCrrrrrrrrrrrrrrrrrrrrrrrrr + ExpectedTree<5> et4 = {{ 0, 5, 15, 25, 50 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , C , C , Rs , Rl }, + {-1 , si_1 , si_1 , si_1 , si_1 , -1 }, + {-1 , -1 , si_3 , si_4 , -1 , -1 }}; + check_tree(tree, et4, __LINE__); + } + {// uncommit should not store any call-stack + Tree tree; + tree.reserve_mapping(0, 50, rd_Test_cs1); + + tree.commit_mapping(10, 10, rd_None_cs2, true); + + tree.commit_mapping(0, 5, rd_None_cs2, true); + + tree.uncommit_mapping(0, 3, rd_None_cs2); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrCCrrrrrCCCCCCCCCCrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr + ExpectedTree<6> et1 = {{ 0, 3, 5, 10, 20, 50 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , C , Rs , C , Rs , Rl }, + {-1 , si_1 , si_1 , si_1 , si_1 , si_1 , -1 }, + {-1 , -1 , si_2 , -1 , si_2 , -1 , -1 }}; + check_tree(tree, et1, __LINE__); + + tree.uncommit_mapping(5, 10, rd_None_cs2); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrCCrrrrrrrrrrCCCCCrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr. + ExpectedTree<6> et2 = {{ 0, 3, 5, 15, 20, 50 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , C , Rs , C , Rs , Rl }, + {-1 , si_1 , si_1 , si_1 , si_1 , si_1 , -1 }, + {-1 , -1 , si_2 , -1 , si_2 , -1 , -1 }}; + check_tree(tree, et2, __LINE__); + } + {// reserve after reserve, but only different call-stacks + SIndex si_4 = si[3]; + VMATree::RegionData call_stack_4(si_4, mtTest); + + Tree tree; + tree.reserve_mapping(0, 50, rd_Test_cs1); + tree.reserve_mapping(10, 10, call_stack_4); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr + ExpectedTree<4> et1 = {{ 0, 10, 20, 50 }, + {mtNone, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rs , Rs , Rl }, + {-1 , si_1 , si_4 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 }}; + check_tree(tree, et1, __LINE__); + } + {// commit without reserve + Tree tree; + tree.commit_mapping(0, 50, rd_Test_cs1); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC + ExpectedTree<2> et = {{ 0, 50 }, + {mtNone, mtTest, mtNone}, + {Rl , C , Rl }, + {-1 , si_1 , -1 }, + {-1 , si_1 , -1 }}; + check_tree(tree, et, __LINE__); + } + {// reserve after commit + Tree tree; + tree.commit_mapping(0, 50, rd_None_cs2); + tree.reserve_mapping(0, 50, rd_Test_cs1); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr + ExpectedTree<2> et = {{ 0, 50 }, + {mtNone, mtTest, mtNone}, + {Rl , Rs , Rl }, + {-1 , si_1 , -1 }, + {-1 , -1 , -1 }}; + check_tree(tree, et, __LINE__); + } +} + +TEST_VM_F(NMTVMATreeTest, OverlapTableRows0To3) { + using SIndex = NativeCallStackStorage::StackIndex; + using State = VMATree::StateType; + SIndex si_1 = si[0]; + SIndex si_2 = si[1]; + SIndex si_3 = si[2]; + + const State Rs = State::Reserved; + const State Rl = State::Released; + const State C = State::Committed; + VMATree::RegionData rd_Test_cs1(si_1, mtTest); + VMATree::RegionData rd_None_cs1(si_1, mtNone); + VMATree::RegionData rd_Test_cs2(si_2, mtTest); + VMATree::RegionData rd_None_cs2(si_2, mtNone); + VMATree::RegionData rd_None_cs3(si_3, mtNone); + + // row 0: .........A..................B..... + // case of empty tree is already covered in other tests. + // row 1 is impossible. See the implementation. + { + // row 2: .........A...Y.......................W.....B.......... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr......................................... + Tree tree; + ExpectedTree<5> pre = {{ 10, 12, 14, 16, 20 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rs , Rs , Rs , Rl }, + {-1 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....CCCCCCCCCCCCCCCCCCCC.......................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10); + ExpectedTree<6> et = {{ 5, 10, 12, 14, 16, 25 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , C , C , C , C , C , Rl }, + {-1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 3: .........A...Y.......................WB..... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // ..........rrrrrrrrrr............................... + Tree tree; + ExpectedTree<5> pre = {{ 10, 12, 14, 16, 20 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rs , Rs , Rs , Rl }, + {-1 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 15, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....CCCCCCCCCCCCCCC............................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 5); + ExpectedTree<6> et = {{ 5, 10, 12, 14, 16, 20 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , C , C , C , C , C , Rl }, + {-1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } +} + +TEST_VM_F(NMTVMATreeTest, OverlapTableRows4to7) { + using SIndex = NativeCallStackStorage::StackIndex; + using State = VMATree::StateType; + SIndex si_1 = si[0]; + SIndex si_2 = si[1]; + SIndex si_3 = si[2]; + + const State Rs = State::Reserved; + const State Rl = State::Released; + const State C = State::Committed; + VMATree::RegionData rd_Test_cs1(si_1, mtTest); + VMATree::RegionData rd_None_cs1(si_1, mtNone); + VMATree::RegionData rd_Test_cs2(si_2, mtTest); + VMATree::RegionData rd_None_cs2(si_2, mtNone); + VMATree::RegionData rd_None_cs3(si_3, mtNone); + + { + // row 4: .....X...A..................B..... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr......................................... + Tree tree; + ExpectedTree<2> pre = {{ 0, 10, }, + {mtNone, mtTest, mtNone}, + {Rl , Rs , Rl }, + {-1 , si_1 , -1 }, + {-1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(20, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr..........CCCCCCCCCCCCCCCCCCCC........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20); + ExpectedTree<4> et = {{ 0, 10, 20, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , C , Rl }, + {-1 , si_1 , -1 , si_2 , -1 }, + {-1 , -1 , -1 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 5: .....X...A...YW.............B..... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....rrrrrrrrrr.................................... + Tree tree; + ExpectedTree<2> pre = {{ 5, 15, }, + {mtNone, mtTest, mtNone}, + {Rl , Rs , Rl }, + {-1 , si_1 , -1 }, + {-1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(10, 10, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....rrrrrCCCCCCCCCC............................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 10); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20 - 15); + ExpectedTree<4> et = {{ 5, 10, 15, 20 }, + {mtNone, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , C , C , Rl }, + {-1 , si_1 , si_1 , si_2 , -1 }, + {-1 , -1 , si_2 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 6: .....X...A.....Y.......................W.....B... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr.....rrrrrrrrrr............................... + Tree tree; + ExpectedTree<7> pre = {{ 0, 5, 10, 12, 14, 16, 20 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rs , Rs , Rs , Rl }, + {-1 , si_1 , -1 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(7, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr..CCCCCCCCCCCCCCCCCCCC........................ + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10); + ExpectedTree<8> et = {{ 0, 5, 7, 10, 12, 14, 16, 27 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rl , C , C , C , C , C , Rl }, + {-1 , si_1 , -1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , -1 , -1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 7: .....X...A...Y.......................WB..... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr.....rrrrrrrrrr............................... + Tree tree; + ExpectedTree<7> pre = {{ 0, 5, 10, 12, 14, 16, 20 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rs , Rs , Rs , Rl }, + {-1 , si_1 , -1 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(7, 13, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr..CCCCCCCCCCCCC............................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 13); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 3); + ExpectedTree<8> et = {{ 0, 5, 7, 10, 12, 14, 16, 20 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rl , C , C , C , C , C , Rl }, + {-1 , si_1 , -1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , -1 , -1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } + +} + +TEST_VM_F(NMTVMATreeTest, OverlapTableRows8to11) { + using SIndex = NativeCallStackStorage::StackIndex; + using State = VMATree::StateType; + SIndex si_1 = si[0]; + SIndex si_2 = si[1]; + SIndex si_3 = si[2]; + + const State Rs = State::Reserved; + const State Rl = State::Released; + const State C = State::Committed; + VMATree::RegionData rd_Test_cs1(si_1, mtTest); + VMATree::RegionData rd_None_cs1(si_1, mtNone); + VMATree::RegionData rd_Test_cs2(si_2, mtTest); + VMATree::RegionData rd_None_cs2(si_2, mtNone); + VMATree::RegionData rd_None_cs3(si_3, mtNone); + { + // row 8: ........XA..................B..... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr......................................... + // nodes: 0--------50........................... + // si1 + // - + // request: 50*****************250 + // post: 0--------50*****************250 + // si1 si2 + // - si2 + Tree tree; + ExpectedTree<2> pre = {{ 0, 10, }, + {mtNone, mtTest, mtNone}, + {Rl , Rs , Rl }, + {-1 , si_1 , -1 }, + {-1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(10, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrrCCCCCCCCCCCCCCCCCCCC..................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20); + ExpectedTree<3> et = {{ 0, 10, 30 }, + {mtNone, mtTest, mtTest, mtNone}, + {Rl , Rs , C , Rl }, + {-1 , si_1 , si_2 , -1 }, + {-1 , -1 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 9: ........XA....YW.............B..... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr......................................... + Tree tree; + ExpectedTree<2> pre = {{ 0, 10, }, + {mtNone, mtTest, mtNone}, + {Rl , Rs , Rl }, + {-1 , si_1 , -1 }, + {-1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(0, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // CCCCCCCCCCCCCCCCCCCC............................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10); + ExpectedTree<3> et = {{ 0, 10, 20 }, + {mtNone, mtTest, mtTest, mtNone}, + {Rl , C , C , Rl }, + {-1 , si_1 , si_2 , -1 }, + {-1 , si_2 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 10: ........XA...Y.......................W.....B... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....rrrrrrrrrrrrrrr............................... + Tree tree; + ExpectedTree<6> pre = {{ 5, 10, 12, 14, 16, 20 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rs , Rs , Rs , Rs , Rl }, + {-1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....CCCCCCCCCCCCCCCCCCCC.......................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 25 - 20); + ExpectedTree<6> et = {{ 5, 10, 12, 14, 16, 25 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , C , C , C , C , C , Rl }, + {-1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 11: ........XA...Y.......................WB..... + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....rrrrrrrrrrrrrrr............................... + Tree tree; + ExpectedTree<6> pre = {{ 5, 10, 12, 14, 16, 20 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rs , Rs , Rs , Rs , Rl }, + {-1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 15, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....CCCCCCCCCCCCCCC............................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 0); + ExpectedTree<6> et = {{ 5, 10, 12, 14, 16, 20 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , C , C , C , C , C , Rl }, + {-1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 }, + {-1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 } + }; + check_tree(tree, et, __LINE__); + } + +} + +TEST_VM_F(NMTVMATreeTest, OverlapTableRows12to15) { + using SIndex = NativeCallStackStorage::StackIndex; + using State = VMATree::StateType; + SIndex si_1 = si[0]; + SIndex si_2 = si[1]; + SIndex si_3 = si[2]; + + const State Rs = State::Reserved; + const State Rl = State::Released; + const State C = State::Committed; + VMATree::RegionData rd_Test_cs1(si_1, mtTest); + VMATree::RegionData rd_None_cs1(si_1, mtNone); + VMATree::RegionData rd_Test_cs2(si_2, mtTest); + VMATree::RegionData rd_None_cs2(si_2, mtNone); + VMATree::RegionData rd_None_cs3(si_3, mtNone); + + { + // row 12: .........A..................B.....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // ..............................rrrrrrrrrr........... + Tree tree; + ExpectedTree<2> pre = {{ 30, 40 }, + {mtNone, mtTest, mtNone}, + {Rl , Rs , Rl }, + {-1 , si_1 , -1 }, + {-1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....CCCCCCCCCCCCCCCCCCCC.....rrrrrrrrrr........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20); + ExpectedTree<4> et = {{ 5, 25, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtNone}, + {Rl , C , Rl , Rs , Rl }, + {-1 , si_2 , -1 , si_1 , -1 }, + {-1 , si_2 , -1 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 13: .........A...YW.............B....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // ..........rrrrrrrrrrrrrrrrrrrr..................... + Tree tree; + ExpectedTree<2> pre = {{ 10, 30 }, + {mtNone, mtTest, mtNone}, + {Rl , Rs , Rl }, + {-1 , si_1 , -1 }, + {-1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....CCCCCCCCCCCCCCCCCCCCrrrrr..................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 30 - 25); + ExpectedTree<4> et = {{ 5, 10, 25, 30 }, + {mtNone, mtTest, mtTest, mtTest, mtNone}, + {Rl , C , C , Rs , Rl }, + {-1 , si_2 , si_1 , si_1 , -1 }, + {-1 , si_2 , si_2 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 14: .........A...Y.......................W....B....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // ..........rrrrrrrrrr..........rrrrrrrrrr........... + Tree tree; + ExpectedTree<7> pre = {{ 10, 12, 14, 16, 20, 30, 40 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rs , Rs , Rs , Rl , Rs , Rl }, + {-1 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....CCCCCCCCCCCCCCCCCCCC.....rrrrrrrrrr........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, (10 - 5) + ( 25 - 20)); + ExpectedTree<8> et = {{ 5, 10, 12, 14, 16, 25, 30, 40 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , C , C , C , C , C , Rl , Rs , Rl }, + {-1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 15: .........A...Y.......................WB....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // ..........rrrrrrrrrr..........rrrrrrrrrr........... + Tree tree; + ExpectedTree<7> pre = {{ 10, 12, 14, 16, 20, 30, 40 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rs , Rs , Rs , Rl , Rs , Rl }, + {-1 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 15, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // .....CCCCCCCCCCCCCCC..........rrrrrrrrrr........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10 - 5); + ExpectedTree<8> et = {{ 5, 10, 12, 14, 16, 20, 30, 40 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , C , C , C , C , C , Rl , Rs , Rl }, + {-1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + +} + +TEST_VM_F(NMTVMATreeTest, OverlapTableRows16to19) { + using SIndex = NativeCallStackStorage::StackIndex; + using State = VMATree::StateType; + SIndex si_1 = si[0]; + SIndex si_2 = si[1]; + SIndex si_3 = si[2]; + + const State Rs = State::Reserved; + const State Rl = State::Released; + const State C = State::Committed; + VMATree::RegionData rd_Test_cs1(si_1, mtTest); + VMATree::RegionData rd_None_cs1(si_1, mtNone); + VMATree::RegionData rd_Test_cs2(si_2, mtTest); + VMATree::RegionData rd_None_cs2(si_2, mtNone); + VMATree::RegionData rd_None_cs3(si_3, mtNone); + { + // row 16: .....X...A..................B....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr....................rrrrrrrrrr........... + Tree tree; + ExpectedTree<4> pre = {{ 0, 10, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(15, 10, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr.....CCCCCCCCCC.....rrrrrrrrrr........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 10); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10); + ExpectedTree<6> et = {{ 0, 10, 15, 25, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , C , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , si_2 , -1 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 17: .....X...A...YW.............B....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr..........rrrrrrrrrr..................... + Tree tree; + ExpectedTree<4> pre = {{ 0, 10, 20, 30 }, + {mtNone, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(15, 10, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr.....CCCCCCCCCCrrrrr..................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 10); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20 - 15); + ExpectedTree<6> et = {{ 0, 10, 15, 20, 25, 30 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , Rl , C , C , Rs , Rl }, + {-1 , si_1 , -1 , si_2 , si_1 , si_1 , -1 }, + {-1 , -1 , -1 , si_2 , si_2 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 18: ....X....A...Y.......................W....B....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr.....rrrrrrrrrr..........rrrrrrrrrr........... + Tree tree; + ExpectedTree<9> pre = {{ 0, 5, 10, 12, 14, 16, 20, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rs , Rs , Rs , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_2 , si_1 , si_2 , si_1 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(7, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr..CCCCCCCCCCCCCCCCCCCC...rrrrrrrrrr........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, (10 - 7) + (27 - 20)); + ExpectedTree<10> et = {{ 0, 5, 7, 12, 14, 16, 20, 27, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , C , C , C , C , C , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 19: .....X...A...Y.......................WB....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr.....rrrrrrrrrr..........rrrrrrrrrr........... + Tree tree; + ExpectedTree<9> pre = {{ 0, 5, 10, 12, 14, 16, 20, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rs , Rs , Rs , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(7, 13, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr..CCCCCCCCCCCCC..........rrrrrrrrrr........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 13); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10 - 7); + ExpectedTree<10> et = {{ 0, 5, 7, 10, 12, 14, 16, 20, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , C , C , C , C , C , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + +} + +TEST_VM_F(NMTVMATreeTest, OverlapTableRows20to23) { + using SIndex = NativeCallStackStorage::StackIndex; + using State = VMATree::StateType; + SIndex si_1 = si[0]; + SIndex si_2 = si[1]; + SIndex si_3 = si[2]; + + const State Rs = State::Reserved; + const State Rl = State::Released; + const State C = State::Committed; + VMATree::RegionData rd_Test_cs1(si_1, mtTest); + VMATree::RegionData rd_None_cs1(si_1, mtNone); + VMATree::RegionData rd_Test_cs2(si_2, mtTest); + VMATree::RegionData rd_None_cs2(si_2, mtNone); + VMATree::RegionData rd_None_cs3(si_3, mtNone); + + { + // row 20: ........XA..................B....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr....................rrrrrrrrrr........... + Tree tree; + ExpectedTree<4> pre = {{ 0, 10, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(10, 15, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrrCCCCCCCCCCCCCCC.....rrrrrrrrrr........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 15); + ExpectedTree<5> et = {{ 0, 10, 25, 30, 40 }, + {mtNone, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , C , Rl , Rs , Rl }, + {-1 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , si_2 , -1 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 21: ........XA...YW.............B....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrr..........rrrrrrrrrr..................... + Tree tree; + ExpectedTree<4> pre = {{ 0, 10, 20, 30 }, + {mtNone, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(10, 15, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrrrrrrCCCCCCCCCCCCCCCrrrrr..................... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 20 - 10); + ExpectedTree<5> et = {{ 0, 10, 20, 25, 30 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtNone}, + {Rl , Rs , C , C , Rs , Rl }, + {-1 , si_1 , si_2 , si_1 , si_1 , -1 }, + {-1 , -1 , si_2 , si_2 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 22: ........XA...Y.......................W....B....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr.....rrrrrrrrrr..........rrrrrrrrrr........... + Tree tree; + ExpectedTree<9> pre = {{ 0, 5, 10, 12, 14, 16, 20, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rs , Rs , Rs , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_2 , si_1 , si_2 , si_1 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 20, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrCCCCCCCCCCCCCCCCCCCC.....rrrrrrrrrr........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 20); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, (10 - 5) + (25 - 20)); + ExpectedTree<9> et = {{ 0, 5, 12, 14, 16, 20, 25, 30, 40 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , C , C , C , C , C , Rl , Rs , Rl }, + {-1 , si_1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + { + // row 23: ........XA...Y.......................WB....U + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrr.....rrrrrrrrrr..........rrrrrrrrrr........... + Tree tree; + ExpectedTree<9> pre = {{ 0, 5, 10, 12, 14, 16, 20, 30, 40 }, + {mtNone, mtTest, mtNone, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , Rl , Rs , Rs , Rs , Rs , Rl , Rs , Rl }, + {-1 , si_1 , -1 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 } + }; + create_tree(tree, pre, __LINE__); + VMATree::SummaryDiff diff = tree.commit_mapping(5, 15, rd_Test_cs2, false); + // 1 2 3 4 5 + // 012345678901234567890123456789012345678901234567890 + // rrrrrCCCCCCCCCCCCCCC..........rrrrrrrrrr........... + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].commit, 15); + EXPECT_EQ(diff.tag[NMTUtil::tag_to_index(mtTest)].reserve, 10 - 5); + ExpectedTree<9> et = {{ 0, 5, 10, 12, 14, 16, 20, 30, 40 }, + {mtNone, mtTest, mtTest, mtTest, mtTest, mtTest, mtTest, mtNone, mtTest, mtNone}, + {Rl , Rs , C , C , C , C , C , Rl , Rs , Rl }, + {-1 , si_1 , si_2 , si_1 , si_2 , si_1 , si_2 , -1 , si_1 , -1 }, + {-1 , -1 , si_2 , si_2 , si_2 , si_2 , si_2 , -1 , -1 , -1 } + }; + check_tree(tree, et, __LINE__); + } + +} + +TEST_VM_F(NMTVMATreeTest, UpdateRegionTest) { + using State = VMATree::StateType; + using SIndex = VMATree::SIndex; + SIndex ES = NativeCallStackStorage::invalid; + SIndex s0 = si[0]; + SIndex s1 = si[1]; + SIndex s2 = si[2]; + + const State Rs = State::Reserved; + const State Rl = State::Released; + const State C = State::Committed; + const int a = 100; + const MemTag ReqTag = mtTest; + const VMATree::RequestInfo ReleaseRequest{0, a, Rl, mtNone, ES, false}; + const VMATree::RequestInfo ReserveRequest{0, a, Rs, ReqTag, s2, false}; + const VMATree::RequestInfo CommitRequest{0, a, C, ReqTag, s2, false}; + const VMATree::RequestInfo UncommitRequest{0, a, Rs, mtNone, ES, true}; + const VMATree::RequestInfo CopyTagCommitRequest{0, a, C, ReqTag, s2, true}; + // existing state request expected state expected diff + // st tag stacks st tag stacks reserve commit + // -- ------ ------ ---------------------- -- ------ ------ ------- ------- + UpdateCallInfo call_info[]={{{Rl, mtNone, ES, ES}, ReleaseRequest, {Rl, mtNone, ES, ES}, {0, 0}, {0, 0}}, + {{Rl, mtNone, ES, ES}, ReserveRequest, {Rs, ReqTag, s2, ES}, {0, a}, {0, 0}}, + {{Rl, mtNone, ES, ES}, CommitRequest, { C, ReqTag, s2, s2}, {0, a}, {0, a}}, + {{Rl, mtNone, ES, ES}, CopyTagCommitRequest, { C, mtNone, s2, s2}, {0, a}, {0, a}}, + {{Rl, mtNone, ES, ES}, UncommitRequest, {Rl, mtNone, ES, ES}, {0, 0}, {0, 0}}, + {{Rs, mtGC, s0, ES}, ReleaseRequest, {Rl, mtNone, ES, ES}, {-a, 0}, {0, 0}}, + {{Rs, mtGC, s0, ES}, ReserveRequest, {Rs, ReqTag, s2, ES}, {-a, a}, {0, 0}}, // diff tag + {{Rs, mtTest, s0, ES}, ReserveRequest, {Rs, ReqTag, s2, ES}, {0, 0}, {0, 0}}, // same tag + {{Rs, mtGC, s0, ES}, CommitRequest, { C, ReqTag, s0, s2}, {-a, a}, {0, a}}, + {{Rs, mtGC, s0, ES}, CopyTagCommitRequest, { C, mtGC, s0, s2}, {0, 0}, {0, a}}, + {{Rs, mtGC, s0, ES}, UncommitRequest, {Rs, mtGC, s0, ES}, {0, 0}, {0, 0}}, + {{ C, mtGC, s0, s1}, ReleaseRequest, {Rl, mtNone, ES, ES}, {-a, 0}, {-a, 0}}, + {{ C, mtGC, s0, s1}, ReserveRequest, {Rs, ReqTag, s2, ES}, {-a, a}, {-a, 0}}, // diff tag + {{ C, mtTest, s0, s1}, ReserveRequest, {Rs, ReqTag, s2, ES}, {0, 0}, {-a, 0}}, // same tag + {{ C, mtGC, s0, s1}, CommitRequest, { C, ReqTag, s0, s2}, {-a, a}, {-a, a}}, + {{ C, mtGC, s0, s1}, CopyTagCommitRequest, { C, mtGC, s0, s2}, {0, 0}, {-a, a}}, + {{ C, mtGC, s0, s1}, UncommitRequest, {Rs, mtGC, s0, ES}, {0, 0}, {-a, 0}} + }; + for (auto ci : call_info) { + call_update_region(ci); + } } \ No newline at end of file From 1fcede053cca360c96606c1034b2a365a4fada82 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Thu, 12 Jun 2025 15:02:38 +0000 Subject: [PATCH 027/213] 8358334: C2/Shenandoah: incorrect execution with Unsafe Reviewed-by: wkemper, shade --- .../gc/shenandoah/c2/shenandoahSupport.cpp | 85 +++++++++++-------- .../gc/shenandoah/c2/shenandoahSupport.hpp | 11 ++- .../TestLostAntiDependencyAtExpansion.java | 67 +++++++++++++++ 3 files changed, 127 insertions(+), 36 deletions(-) create mode 100644 test/hotspot/jtreg/gc/shenandoah/compiler/TestLostAntiDependencyAtExpansion.java diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 56d88d44d27..807d4197b12 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -625,6 +625,34 @@ void ShenandoahBarrierC2Support::verify(RootNode* root) { } #endif +bool ShenandoahBarrierC2Support::is_anti_dependent_load_at_control(PhaseIdealLoop* phase, Node* maybe_load, Node* store, + Node* control) { + return maybe_load->is_Load() && phase->C->can_alias(store->adr_type(), phase->C->get_alias_index(maybe_load->adr_type())) && + phase->ctrl_or_self(maybe_load) == control; +} + +void ShenandoahBarrierC2Support::maybe_push_anti_dependent_loads(PhaseIdealLoop* phase, Node* maybe_store, Node* control, Unique_Node_List &wq) { + if (!maybe_store->is_Store() && !maybe_store->is_LoadStore()) { + return; + } + Node* mem = maybe_store->in(MemNode::Memory); + for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) { + Node* u = mem->fast_out(i); + if (is_anti_dependent_load_at_control(phase, u, maybe_store, control)) { + wq.push(u); + } + } +} + +void ShenandoahBarrierC2Support::push_data_inputs_at_control(PhaseIdealLoop* phase, Node* n, Node* ctrl, Unique_Node_List &wq) { + for (uint i = 0; i < n->req(); i++) { + Node* in = n->in(i); + if (in != nullptr && phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl) { + wq.push(in); + } + } +} + bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node* n, PhaseIdealLoop* phase) { // That both nodes have the same control is not sufficient to prove // domination, verify that there's no path from d to n @@ -639,22 +667,9 @@ bool ShenandoahBarrierC2Support::is_dominator_same_ctrl(Node* c, Node* d, Node* if (m->is_Phi() && m->in(0)->is_Loop()) { assert(phase->ctrl_or_self(m->in(LoopNode::EntryControl)) != c, "following loop entry should lead to new control"); } else { - if (m->is_Store() || m->is_LoadStore()) { - // Take anti-dependencies into account - Node* mem = m->in(MemNode::Memory); - for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) { - Node* u = mem->fast_out(i); - if (u->is_Load() && phase->C->can_alias(m->adr_type(), phase->C->get_alias_index(u->adr_type())) && - phase->ctrl_or_self(u) == c) { - wq.push(u); - } - } - } - for (uint i = 0; i < m->req(); i++) { - if (m->in(i) != nullptr && phase->ctrl_or_self(m->in(i)) == c) { - wq.push(m->in(i)); - } - } + // Take anti-dependencies into account + maybe_push_anti_dependent_loads(phase, m, c, wq); + push_data_inputs_at_control(phase, m, c, wq); } } return true; @@ -1006,7 +1021,20 @@ void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* lo phase->register_new_node(val, ctrl); } -void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase) { +void ShenandoahBarrierC2Support::collect_nodes_above_barrier(Unique_Node_List &nodes_above_barrier, PhaseIdealLoop* phase, Node* ctrl, Node* init_raw_mem) { + nodes_above_barrier.clear(); + if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) { + nodes_above_barrier.push(init_raw_mem); + } + for (uint next = 0; next < nodes_above_barrier.size(); next++) { + Node* n = nodes_above_barrier.at(next); + // Take anti-dependencies into account + maybe_push_anti_dependent_loads(phase, n, ctrl, nodes_above_barrier); + push_data_inputs_at_control(phase, n, ctrl, nodes_above_barrier); + } +} + +void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& nodes_above_barrier, uint last, PhaseIdealLoop* phase) { Node* ctrl = phase->get_ctrl(barrier); Node* init_raw_mem = fixer.find_mem(ctrl, barrier); @@ -1017,30 +1045,17 @@ void ShenandoahBarrierC2Support::fix_ctrl(Node* barrier, Node* region, const Mem // control will be after the expanded barrier. The raw memory (if // its memory is control dependent on the barrier's input control) // must stay above the barrier. - uses_to_ignore.clear(); - if (phase->has_ctrl(init_raw_mem) && phase->get_ctrl(init_raw_mem) == ctrl && !init_raw_mem->is_Phi()) { - uses_to_ignore.push(init_raw_mem); - } - for (uint next = 0; next < uses_to_ignore.size(); next++) { - Node *n = uses_to_ignore.at(next); - for (uint i = 0; i < n->req(); i++) { - Node* in = n->in(i); - if (in != nullptr && phase->has_ctrl(in) && phase->get_ctrl(in) == ctrl) { - uses_to_ignore.push(in); - } - } - } + collect_nodes_above_barrier(nodes_above_barrier, phase, ctrl, init_raw_mem); for (DUIterator_Fast imax, i = ctrl->fast_outs(imax); i < imax; i++) { Node* u = ctrl->fast_out(i); if (u->_idx < last && u != barrier && !u->depends_only_on_test() && // preserve dependency on test - !uses_to_ignore.member(u) && + !nodes_above_barrier.member(u) && (u->in(0) != ctrl || (!u->is_Region() && !u->is_Phi())) && (ctrl->Opcode() != Op_CatchProj || u->Opcode() != Op_CreateEx)) { Node* old_c = phase->ctrl_or_self(u); - Node* c = old_c; - if (c != ctrl || + if (old_c != ctrl || is_dominator_same_ctrl(old_c, barrier, u, phase) || ShenandoahBarrierSetC2::is_shenandoah_state_load(u)) { phase->igvn().rehash_node_delayed(u); @@ -1315,7 +1330,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { // Expand load-reference-barriers MemoryGraphFixer fixer(Compile::AliasIdxRaw, true, phase); - Unique_Node_List uses_to_ignore; + Unique_Node_List nodes_above_barriers; for (int i = state->load_reference_barriers_count() - 1; i >= 0; i--) { ShenandoahLoadReferenceBarrierNode* lrb = state->load_reference_barrier(i); uint last = phase->C->unique(); @@ -1410,7 +1425,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { Node* out_val = val_phi; phase->register_new_node(val_phi, region); - fix_ctrl(lrb, region, fixer, uses, uses_to_ignore, last, phase); + fix_ctrl(lrb, region, fixer, uses, nodes_above_barriers, last, phase); ctrl = orig_ctrl; diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp index 93572cddc5b..63e8412a307 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.hpp @@ -62,8 +62,12 @@ class ShenandoahBarrierC2Support : public AllStatic { PhaseIdealLoop* phase, int flags); static void call_lrb_stub(Node*& ctrl, Node*& val, Node* load_addr, DecoratorSet decorators, PhaseIdealLoop* phase); + + static void collect_nodes_above_barrier(Unique_Node_List &nodes_above_barrier, PhaseIdealLoop* phase, Node* ctrl, + Node* init_raw_mem); + static void test_in_cset(Node*& ctrl, Node*& not_cset_ctrl, Node* val, Node* raw_mem, PhaseIdealLoop* phase); - static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& uses_to_ignore, uint last, PhaseIdealLoop* phase); + static void fix_ctrl(Node* barrier, Node* region, const MemoryGraphFixer& fixer, Unique_Node_List& uses, Unique_Node_List& nodes_above_barrier, uint last, PhaseIdealLoop* phase); static Node* get_load_addr(PhaseIdealLoop* phase, VectorSet& visited, Node* lrb); public: @@ -76,6 +80,11 @@ class ShenandoahBarrierC2Support : public AllStatic { static bool expand(Compile* C, PhaseIterGVN& igvn); static void pin_and_expand(PhaseIdealLoop* phase); + static void push_data_inputs_at_control(PhaseIdealLoop* phase, Node* n, Node* ctrl, + Unique_Node_List &wq); + static bool is_anti_dependent_load_at_control(PhaseIdealLoop* phase, Node* maybe_load, Node* store, Node* control); + + static void maybe_push_anti_dependent_loads(PhaseIdealLoop* phase, Node* maybe_store, Node* control, Unique_Node_List &wq); #ifdef ASSERT static void verify(RootNode* root); #endif diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLostAntiDependencyAtExpansion.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLostAntiDependencyAtExpansion.java new file mode 100644 index 00000000000..bcdf964a1fa --- /dev/null +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLostAntiDependencyAtExpansion.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8358334 + * @summary C2/Shenandoah: incorrect execution with Unsafe + * @requires vm.gc.Shenandoah + * @modules java.base/jdk.internal.misc:+open + * + * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:-TieredCompilation -XX:+UseShenandoahGC + * TestLostAntiDependencyAtExpansion + * + * + */ + +import jdk.internal.misc.Unsafe; + +public class TestLostAntiDependencyAtExpansion { + static final jdk.internal.misc.Unsafe UNSAFE = Unsafe.getUnsafe(); + + public static void main(String[] args) { + long addr = UNSAFE.allocateMemory(8); + for (int i = 0; i < 20_000; i++) { + UNSAFE.putLong(addr, 42L); + long res = test1(addr); + if (res != 42L) { + throw new RuntimeException("Incorrect result: " + res); + } + } + } + + static class A { + long field; + } + + static A a = new A(); + + private static long test1(long addr) { + long tmp = UNSAFE.getLong(addr); + + UNSAFE.putLong(addr, 0L); + + return tmp + a.field; + } + +} From 3c53057fa63e0f8bf3634e4286fe2085d2f4ee9e Mon Sep 17 00:00:00 2001 From: David Briemann Date: Thu, 12 Jun 2025 15:27:44 +0000 Subject: [PATCH 028/213] 8359232: [PPC64] C2: Clean up ppc.ad: add instr sizes, remove comments Reviewed-by: mdoerr --- src/hotspot/cpu/ppc/ppc.ad | 29 ++++++++++------------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index d8e00cfef89..1504c977fc7 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -6687,6 +6687,7 @@ instruct reinterpretL(iRegLdst dst) %{ match(Set dst (VectorReinterpret dst)); ins_cost(0); format %{ "reinterpret $dst" %} + size(0); ins_encode( /*empty*/ ); ins_pipe(pipe_class_empty); %} @@ -6695,6 +6696,7 @@ instruct reinterpretX(vecX dst) %{ match(Set dst (VectorReinterpret dst)); ins_cost(0); format %{ "reinterpret $dst" %} + size(0); ins_encode( /*empty*/ ); ins_pipe(pipe_class_empty); %} @@ -6814,7 +6816,6 @@ instruct cond_set_0_oop(iRegNdst dst, flagsRegSrc crx, iRegPsrc src1) %{ format %{ "CMOVE $dst, $crx eq, 0, $src1 \t// encode: preserve 0" %} size(4); ins_encode %{ - // This is a Power7 instruction for which no machine description exists. __ isel_0($dst$$Register, $crx$$CondRegister, Assembler::equal, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -6946,7 +6947,6 @@ instruct cond_set_0_ptr(iRegPdst dst, flagsRegSrc crx, iRegPsrc src1) %{ format %{ "CMOVE $dst, $crx eq, 0, $src1 \t// decode: preserve 0" %} size(4); ins_encode %{ - // This is a Power7 instruction for which no machine description exists. __ isel_0($dst$$Register, $crx$$CondRegister, Assembler::equal, $src1$$Register); %} ins_pipe(pipe_class_default); @@ -7423,8 +7423,6 @@ instruct cmovI_reg_isel(cmpOp cmp, flagsRegSrc crx, iRegIdst dst, iRegIsrc src) format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} size(4); ins_encode %{ - // This is a Power7 instruction for which no machine description - // exists. Anyways, the scheduler should be off on Power7. int cc = $cmp$$cmpcode; __ isel($dst$$Register, $crx$$CondRegister, (Assembler::Condition)(cc & 3), /*invert*/((~cc) & 8), $src$$Register); @@ -7440,8 +7438,6 @@ instruct cmovL_reg_isel(cmpOp cmp, flagsRegSrc crx, iRegLdst dst, iRegLsrc src) format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} size(4); ins_encode %{ - // This is a Power7 instruction for which no machine description - // exists. Anyways, the scheduler should be off on Power7. int cc = $cmp$$cmpcode; __ isel($dst$$Register, $crx$$CondRegister, (Assembler::Condition)(cc & 3), /*invert*/((~cc) & 8), $src$$Register); @@ -7457,8 +7453,6 @@ instruct cmovN_reg_isel(cmpOp cmp, flagsRegSrc crx, iRegNdst dst, iRegNsrc src) format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} size(4); ins_encode %{ - // This is a Power7 instruction for which no machine description - // exists. Anyways, the scheduler should be off on Power7. int cc = $cmp$$cmpcode; __ isel($dst$$Register, $crx$$CondRegister, (Assembler::Condition)(cc & 3), /*invert*/((~cc) & 8), $src$$Register); @@ -7474,8 +7468,6 @@ instruct cmovP_reg_isel(cmpOp cmp, flagsRegSrc crx, iRegPdst dst, iRegPsrc src) format %{ "CMOVE $cmp, $crx, $dst, $src\n\t" %} size(4); ins_encode %{ - // This is a Power7 instruction for which no machine description - // exists. Anyways, the scheduler should be off on Power7. int cc = $cmp$$cmpcode; __ isel($dst$$Register, $crx$$CondRegister, (Assembler::Condition)(cc & 3), /*invert*/((~cc) & 8), $src$$Register); @@ -9921,13 +9913,6 @@ instruct andcL_reg_reg(iRegLdst dst, iRegLsrc src1, iRegLsrc src2) %{ // of java.lang.Float etc., e.g. // int floatToIntBits(float value) // float intBitsToFloat(int bits) -// -// Notes on the implementation on ppc64: -// For Power7 and earlier, the rules are limited to those which move between a -// register and a stack-location, because we always have to go through memory -// when moving between a float register and an integer register. -// This restriction is removed in Power8 with the introduction of the mtfprd -// and mffprd instructions. instruct moveL2D_reg(regD dst, iRegLsrc src) %{ match(Set dst (MoveL2D src)); @@ -12434,6 +12419,7 @@ instruct minI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegC effect(KILL cr0); ins_cost(DEFAULT_COST*2); + size(8); ins_encode %{ __ cmpw(CR0, $src1$$Register, $src2$$Register); __ isel($dst$$Register, CR0, Assembler::less, /*invert*/false, $src1$$Register, $src2$$Register); @@ -12447,6 +12433,7 @@ instruct maxI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegC effect(KILL cr0); ins_cost(DEFAULT_COST*2); + size(8); ins_encode %{ __ cmpw(CR0, $src1$$Register, $src2$$Register); __ isel($dst$$Register, CR0, Assembler::greater, /*invert*/false, $src1$$Register, $src2$$Register); @@ -12456,7 +12443,6 @@ instruct maxI_reg_reg_isel(iRegIdst dst, iRegIsrc src1, iRegIsrc src2, flagsRegC //---------- Population Count Instructions ------------------------------------ -// Popcnt for Power7. instruct popCountI(iRegIdst dst, iRegIsrc src) %{ match(Set dst (PopCountI src)); predicate(UsePopCountInstruction); @@ -12470,7 +12456,6 @@ instruct popCountI(iRegIdst dst, iRegIsrc src) %{ ins_pipe(pipe_class_default); %} -// Popcnt for Power7. instruct popCountL(iRegIdst dst, iRegLsrc src) %{ predicate(UsePopCountInstruction); match(Set dst (PopCountL src)); @@ -13299,6 +13284,7 @@ instruct repl2F_immF0(iRegLdst dst, immF_0 zero) %{ Matcher::vector_element_basic_type(n) == T_FLOAT); format %{ "LI $dst, #0 \t// replicate2F" %} + size(4); ins_encode %{ __ li($dst$$Register, 0x0); %} @@ -13927,6 +13913,7 @@ instruct overflowAddL_reg_reg(flagsRegCR0 cr0, iRegLsrc op1, iRegLsrc op2) %{ match(Set cr0 (OverflowAddL op1 op2)); format %{ "add_ $op1, $op2\t# overflow check long" %} + size(12); ins_encode %{ __ li(R0, 0); __ mtxer(R0); // clear XER.SO @@ -13939,6 +13926,7 @@ instruct overflowSubL_reg_reg(flagsRegCR0 cr0, iRegLsrc op1, iRegLsrc op2) %{ match(Set cr0 (OverflowSubL op1 op2)); format %{ "subfo_ R0, $op2, $op1\t# overflow check long" %} + size(12); ins_encode %{ __ li(R0, 0); __ mtxer(R0); // clear XER.SO @@ -13951,6 +13939,7 @@ instruct overflowNegL_reg(flagsRegCR0 cr0, immL_0 zero, iRegLsrc op2) %{ match(Set cr0 (OverflowSubL zero op2)); format %{ "nego_ R0, $op2\t# overflow check long" %} + size(12); ins_encode %{ __ li(R0, 0); __ mtxer(R0); // clear XER.SO @@ -13963,6 +13952,7 @@ instruct overflowMulL_reg_reg(flagsRegCR0 cr0, iRegLsrc op1, iRegLsrc op2) %{ match(Set cr0 (OverflowMulL op1 op2)); format %{ "mulldo_ R0, $op1, $op2\t# overflow check long" %} + size(12); ins_encode %{ __ li(R0, 0); __ mtxer(R0); // clear XER.SO @@ -14001,6 +13991,7 @@ instruct repl4F_immF0(vecX dst, immF_0 zero) %{ Matcher::vector_element_basic_type(n) == T_FLOAT); format %{ "XXLXOR $dst, $zero \t// replicate4F" %} + size(4); ins_encode %{ __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); %} From 8d33ea7395e5dd504b899d8972617f6696546d84 Mon Sep 17 00:00:00 2001 From: jeremy Date: Thu, 12 Jun 2025 16:11:35 +0000 Subject: [PATCH 029/213] 8354646: java.awt.TextField allows to identify the spaces in a password when double clicked at the starting and end of the text Reviewed-by: aivanov, kizune, tr, psadhukhan --- .../plaf/basic/BasicPasswordFieldUI.java | 21 +---- .../javax/swing/plaf/basic/BasicTextUI.java | 18 +++- .../plaf/synth/SynthPasswordFieldUI.java | 17 +--- .../awt/TextField/SetEchoCharWordOpsTest.java | 4 +- .../PasswordSelectionWordTest.java | 94 +++++++++++++++++++ 5 files changed, 115 insertions(+), 39 deletions(-) create mode 100644 test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPasswordFieldUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPasswordFieldUI.java index 6a78e2d6871..ce3b699b886 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPasswordFieldUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPasswordFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,23 +91,4 @@ protected void installDefaults() { public View create(Element elem) { return new PasswordView(elem); } - - /** - * Create the action map for Password Field. This map provides - * same actions for double mouse click and - * and for triple mouse click (see bug 4231444). - */ - - ActionMap createActionMap() { - ActionMap map = super.createActionMap(); - if (map.get(DefaultEditorKit.selectWordAction) != null) { - Action a = map.get(DefaultEditorKit.selectLineAction); - if (a != null) { - map.remove(DefaultEditorKit.selectWordAction); - map.put(DefaultEditorKit.selectWordAction, a); - } - } - return map; - } - } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java index ec0fbaf9928..094f5be68c5 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTextUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -647,6 +647,22 @@ ActionMap createActionMap() { TransferHandler.getCopyAction()); map.put(TransferHandler.getPasteAction().getValue(Action.NAME), TransferHandler.getPasteAction()); + + if (getComponent() instanceof JPasswordField) { + // Edit the action map for Password Field. This map provides + // same actions for double mouse click and + // and for triple mouse click (see bugs 4231444, 8354646). + + if (map.get(DefaultEditorKit.selectWordAction) != null) { + map.remove(DefaultEditorKit.selectWordAction); + + Action a = map.get(DefaultEditorKit.selectLineAction); + if (a != null) { + map.put(DefaultEditorKit.selectWordAction, a); + } + } + } + return map; } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPasswordFieldUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPasswordFieldUI.java index 083a118c209..dbdeac3da1f 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPasswordFieldUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthPasswordFieldUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,19 +108,4 @@ public void paintBorder(SynthContext context, Graphics g, int x, int y, int w, int h) { context.getPainter().paintPasswordFieldBorder(context, g, x, y, w, h); } - - /** - * {@inheritDoc} - */ - @Override - protected void installKeyboardActions() { - super.installKeyboardActions(); - ActionMap map = SwingUtilities.getUIActionMap(getComponent()); - if (map != null && map.get(DefaultEditorKit.selectWordAction) != null) { - Action a = map.get(DefaultEditorKit.selectLineAction); - if (a != null) { - map.put(DefaultEditorKit.selectWordAction, a); - } - } - } } diff --git a/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java b/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java index 825c21fdc96..9116a4dff3b 100644 --- a/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java +++ b/test/jdk/java/awt/TextField/SetEchoCharWordOpsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ /* * @test - * @bug 6191897 + * @bug 6191897 8354646 * @summary Verifies that ctrl+left/right does not move word-by-word in a TextField * with echo character set * @library /java/awt/regtesthelpers /test/lib diff --git a/test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java b/test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java new file mode 100644 index 00000000000..695d8a83c70 --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicTextUI/PasswordSelectionWordTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @key headful + * @bug 4231444 8354646 + * @summary Password fields' ActionMap needs to replace + * DefaultEditorKit.selectWordAction with + * DefaultEditorKit.selectLineAction. + * + * @run main PasswordSelectionWordTest + */ + +import javax.swing.Action; +import javax.swing.JPasswordField; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.basic.BasicTextUI; +import javax.swing.text.DefaultEditorKit; +import java.awt.event.ActionEvent; + +public class PasswordSelectionWordTest { + public static void main(String[] args) throws Exception { + for (UIManager.LookAndFeelInfo laf : + UIManager.getInstalledLookAndFeels()) { + System.out.println("Testing LAF: " + laf.getClassName()); + SwingUtilities.invokeAndWait(() -> { + if (setLookAndFeel(laf)) { + runTest(); + } + }); + } + } + + private static boolean setLookAndFeel(UIManager.LookAndFeelInfo laf) { + try { + UIManager.setLookAndFeel(laf.getClassName()); + return true; + } catch (UnsupportedLookAndFeelException e) { + System.err.println("Skipping unsupported look and feel:"); + e.printStackTrace(); + return false; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void runTest() { + String str = "one two three"; + JPasswordField field = new JPasswordField(str); + if (!(field.getUI() instanceof BasicTextUI)) { + throw new RuntimeException("Unexpected condition: JPasswordField UI was " + field.getUI()); + } + System.out.println("Testing " + field.getUI()); + + // do something (anything) to initialize the Views: + field.setSize(100, 100); + field.addNotify(); + + Action action = field.getActionMap().get( + DefaultEditorKit.selectWordAction); + action.actionPerformed(new ActionEvent(field, 0, "")); + int selectionStart = field.getSelectionStart(); + int selectionEnd = field.getSelectionEnd(); + System.out.println("selectionStart = " + selectionStart); + System.out.println("selectionEnd = " + selectionEnd); + if (selectionStart != 0 || selectionEnd != str.length()) { + throw new RuntimeException("selectionStart = " + selectionStart + + " and selectionEnd = " + selectionEnd); + } + } +} From 610a18e7b3bc9680031a2ba608b89ee6fdec795c Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Thu, 12 Jun 2025 17:10:57 +0000 Subject: [PATCH 030/213] 8358688: HttpClient: Simplify file streaming in RequestPublishers.FilePublisher Reviewed-by: dfuchs, jpai --- .../internal/net/http/RequestPublishers.java | 44 +++++-------------- .../FilePublisher/FilePublisherTest.java | 35 +++++++++++---- .../net/httpclient/RelayingPublishers.java | 4 +- 3 files changed, 39 insertions(+), 44 deletions(-) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java index 305957ae804..dd5443c5035 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java @@ -25,7 +25,6 @@ package jdk.internal.net.http; -import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -35,6 +34,7 @@ import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.file.Files; +import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Collections; @@ -48,7 +48,6 @@ import java.util.concurrent.Flow.Publisher; import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.locks.ReentrantLock; -import java.util.function.Function; import java.util.function.Supplier; import jdk.internal.net.http.common.Demand; @@ -228,30 +227,16 @@ public static class FilePublisher implements BodyPublisher { private final Path path; private final long length; - private final Function inputStreamSupplier; /** * Factory for creating FilePublisher. */ public static FilePublisher create(Path path) throws FileNotFoundException { - boolean defaultFS = true; - try { - path.toFile().getPath(); - } catch (UnsupportedOperationException uoe) { - // path not associated with the default file system provider - defaultFS = false; - } - - // existence check must be after FS checks if (Files.notExists(path)) throw new FileNotFoundException(path + " not found"); - boolean finalDefaultFS = defaultFS; - Function inputStreamSupplier = (p) -> - createInputStream(p, finalDefaultFS); - long length; try { length = Files.size(path); @@ -259,26 +244,12 @@ public static FilePublisher create(Path path) length = -1; } - return new FilePublisher(path, length, inputStreamSupplier); + return new FilePublisher(path, length); } - private static InputStream createInputStream(Path path, - boolean defaultFS) { - try { - return defaultFS - ? new FileInputStream(path.toFile()) - : Files.newInputStream(path); - } catch (IOException io) { - throw new UncheckedIOException(io); - } - } - - private FilePublisher(Path name, - long length, - Function inputStreamSupplier) { + private FilePublisher(Path name, long length) { path = name; this.length = length; - this.inputStreamSupplier = inputStreamSupplier; } @Override @@ -286,7 +257,14 @@ public void subscribe(Flow.Subscriber subscriber) { InputStream is = null; Throwable t = null; try { - is = inputStreamSupplier.apply(path); + // Throw `FileNotFoundException` to match the specification of `BodyPublishers::ofFile + if (!Files.isRegularFile(path)) { + throw new FileNotFoundException(path + " (Not a regular file)"); + } + is = Files.newInputStream(path); + } catch (NoSuchFileException nsfe) { + // Throw `FileNotFoundException` to match the specification of `BodyPublishers::ofFile` + t = new FileNotFoundException(path + " (No such file or directory)"); } catch (UncheckedIOException | UndeclaredThrowableException ue) { t = ue.getCause(); } catch (Throwable th) { diff --git a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.java b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.java index 8bb679a2e74..174afaf3f65 100644 --- a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.java +++ b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,9 @@ /* * @test - * @bug 8235459 - * @summary Confirm that HttpRequest.BodyPublishers#ofFile(Path) - * assumes the default file system + * @bug 8235459 8358688 + * @summary Verifies `HttpRequest.BodyPublishers#ofFile(Path)` against file + * systems that support `Path#toFile()` and also those that don't * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.httpclient.test.lib.common.HttpServerAdapters * jdk.test.lib.net.SimpleSSLContext @@ -39,11 +39,10 @@ import org.testng.annotations.Test; import javax.net.ssl.SSLContext; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.net.InetAddress; -import java.net.InetSocketAddress; import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; @@ -61,6 +60,7 @@ import static java.net.http.HttpClient.Version.HTTP_1_1; import static java.net.http.HttpClient.Version.HTTP_2; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; public class FilePublisherTest implements HttpServerAdapters { SSLContext sslContext; @@ -156,6 +156,26 @@ public void testZipFs(String uriString, send(uriString, path, expectedMsg, sameClient); } + @Test + public void testFileNotFound() throws Exception { + out.printf("\n\n--- testFileNotFound(): starting\n"); + try (FileSystem fs = newZipFs()) { + Path fileInZip = fs.getPath("non-existent.txt"); + BodyPublishers.ofFile(fileInZip); + fail(); + } catch (FileNotFoundException e) { + out.println("Caught expected: " + e); + } + var path = Path.of("fileNotFound.txt"); + try { + Files.deleteIfExists(path); + BodyPublishers.ofFile(path); + fail(); + } catch (FileNotFoundException e) { + out.println("Caught expected: " + e); + } + } + private static final int ITERATION_COUNT = 3; private void send(String uriString, @@ -193,9 +213,6 @@ public void setup() throws Exception { zipFs = newZipFs(); zipFsPath = zipFsFile(zipFs); - InetSocketAddress sa = - new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); - httpTestServer = HttpServerAdapters.HttpTestServer.create(HTTP_1_1); httpTestServer.addHandler(new HttpEchoHandler(), "/http1/echo"); httpURI = "http://" + httpTestServer.serverAuthority() + "/http1/echo"; diff --git a/test/jdk/java/net/httpclient/RelayingPublishers.java b/test/jdk/java/net/httpclient/RelayingPublishers.java index c97d09df352..83d74cd13ae 100644 --- a/test/jdk/java/net/httpclient/RelayingPublishers.java +++ b/test/jdk/java/net/httpclient/RelayingPublishers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ * @test * @summary Verifies that some of the standard BodyPublishers relay exception * rather than throw it - * @bug 8226303 + * @bug 8226303 8358688 * @library /test/lib * @run testng/othervm RelayingPublishers */ From 0ef0986731c23b00510e9501e1627b7712a45b65 Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Thu, 12 Jun 2025 17:12:04 +0000 Subject: [PATCH 031/213] 8359168: Revert stdin.encoding usage in test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach010/attach010Agent00.java Reviewed-by: cjplummer --- .../nsk/jvmti/AttachOnDemand/attach010/attach010Agent00.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach010/attach010Agent00.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach010/attach010Agent00.java index 1e0abf4e11e..877c1e3862e 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach010/attach010Agent00.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach010/attach010Agent00.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -60,8 +60,7 @@ protected void agentActions() throws Throwable { FileInputStream newInputStream = new FileInputStream(inStreamFileName); System.setIn(newInputStream); - BufferedReader inputStreamReader = new BufferedReader(new InputStreamReader( - System.in, System.getProperty("stdin.encoding"))); + BufferedReader inputStreamReader = new BufferedReader(new InputStreamReader(System.in)); int readValue = Integer.parseInt(inputStreamReader.readLine()); if (readValue != valueToWrite) { From 99829950f680936489048a1ad4ce12f166805e4d Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 12 Jun 2025 18:04:14 +0000 Subject: [PATCH 032/213] 8358819: The first year is not displayed correctly in Japanese Calendar Reviewed-by: jlu, joehw, iris --- .../build/tools/cldrconverter/Bundle.java | 34 ++++-- .../Calendar/JapaneseCalendarNameTest.java | 108 ++++++++++++++++++ .../util/Calendar/JapaneseEraNameTest.java | 66 ----------- 3 files changed, 131 insertions(+), 77 deletions(-) create mode 100644 test/jdk/java/util/Calendar/JapaneseCalendarNameTest.java delete mode 100644 test/jdk/java/util/Calendar/JapaneseEraNameTest.java diff --git a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java index d8752bca142..cbef22d91c0 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/Bundle.java @@ -542,10 +542,10 @@ private void handleDateTimeFormatPatterns(String[] patternKeys, Map= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')) { if (count != 0) { - converter.convert(calendarType, lastLetter, count, jrePattern); + converter.convert(calendarType, patternKey, lastLetter, count, jrePattern); lastLetter = 0; count = 0; } @@ -627,7 +627,7 @@ private String translateDateFormatLetters(CalendarType calendarType, String cldr count++; continue; } - converter.convert(calendarType, lastLetter, count, jrePattern); + converter.convert(calendarType, patternKey, lastLetter, count, jrePattern); lastLetter = c; count = 1; } @@ -637,7 +637,7 @@ private String translateDateFormatLetters(CalendarType calendarType, String cldr } if (count != 0) { - converter.convert(calendarType, lastLetter, count, jrePattern); + converter.convert(calendarType, patternKey, lastLetter, count, jrePattern); } if (cldrFormat.contentEquals(jrePattern)) { return cldrFormat; @@ -661,7 +661,7 @@ private String toMetaZoneKey(String tzKey) { * on the support given by the SimpleDateFormat and the j.t.f.DateTimeFormatter * for date-time formatting. */ - private void convertDateTimePatternLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) { + private void convertDateTimePatternLetter(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb) { switch (cldrLetter) { case 'u': case 'U': @@ -683,7 +683,7 @@ private void convertDateTimePatternLetter(CalendarType calendarType, char cldrLe * Perform a conversion of CLDR date-time format pattern letter which is * specific to the SimpleDateFormat. */ - private void convertSDFLetter(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb) { + private void convertSDFLetter(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb) { switch (cldrLetter) { case 'G': if (calendarType != CalendarType.GREGORIAN) { @@ -722,6 +722,17 @@ private void convertSDFLetter(CalendarType calendarType, char cldrLetter, int co appendN('z', count, sb); break; + case 'y': + // If the style is FULL/LONG for a Japanese Calendar, make the + // count == 4 for Gan-nen + if (calendarType == CalendarType.JAPANESE && + (patternKey.contains("full-") || + patternKey.contains("long-"))) { + count = 4; + } + appendN(cldrLetter, count, sb); + break; + case 'Z': if (count == 4 || count == 5) { sb.append("XXX"); @@ -767,6 +778,7 @@ private void handleSkeletonPatterns(Map myMap, CalendarType cale .collect(Collectors.toMap( e -> calendarPrefix + e.getKey(), e -> translateDateFormatLetters(calendarType, + e.getKey(), (String)e.getValue(), this::convertDateTimePatternLetter) )) @@ -775,7 +787,7 @@ private void handleSkeletonPatterns(Map myMap, CalendarType cale @FunctionalInterface private interface ConvertDateTimeLetters { - void convert(CalendarType calendarType, char cldrLetter, int count, StringBuilder sb); + void convert(CalendarType calendarType, String patternKey, char cldrLetter, int count, StringBuilder sb); } /** diff --git a/test/jdk/java/util/Calendar/JapaneseCalendarNameTest.java b/test/jdk/java/util/Calendar/JapaneseCalendarNameTest.java new file mode 100644 index 00000000000..6c8597c9404 --- /dev/null +++ b/test/jdk/java/util/Calendar/JapaneseCalendarNameTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8202088 8207152 8217609 8219890 8358819 + * @summary Test the localized Japanese calendar names, such as + * the Reiwa Era names (May 1st. 2019-), or the Gan-nen text + * @modules jdk.localedata + * @run junit JapaneseCalendarNameTest + */ + +import static java.util.Calendar.*; +import static java.util.Locale.*; + +import java.text.DateFormat; +import java.text.ParseException; +import java.util.Calendar; +import java.util.Locale; +import java.util.stream.Stream; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class JapaneseCalendarNameTest { + private static final Calendar c = new Calendar.Builder() + .setCalendarType("japanese") + .setFields(ERA, 5, YEAR, 1, MONTH, MAY, DAY_OF_MONTH, 1) + .build(); + private static final Locale JAJPJP = Locale.of("ja", "JP", "JP"); + private static final Locale JCAL = Locale.forLanguageTag("ja-u-ca-japanese"); + + private static Stream reiwaEraNames() { + return Stream.of( + // type, locale, name + Arguments.of(LONG, JAPAN, "令和"), + Arguments.of(LONG, US, "Reiwa"), + Arguments.of(LONG, CHINA, "令和"), + Arguments.of(SHORT, JAPAN, "令和"), + Arguments.of(SHORT, US, "Reiwa"), + Arguments.of(SHORT, CHINA, "令和") + ); + } + + @ParameterizedTest + @MethodSource("reiwaEraNames") + void testReiwaEraName(int type, Locale locale, String expected) { + assertEquals(expected, c.getDisplayName(ERA, type, locale)); + } + + private static Stream gannen() { + return Stream.of( + // format, + // formatted text + Arguments.of(DateFormat.getDateInstance(DateFormat.FULL, JAJPJP), + "令和元年5月1日水曜日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.FULL, JCAL), + "令和元年5月1日水曜日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.LONG, JAJPJP), + "令和元年5月1日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.LONG, JCAL), + "令和元年5月1日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.MEDIUM, JAJPJP), + "令和1年5月1日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.MEDIUM, JCAL), + "令和1年5月1日"), + Arguments.of(DateFormat.getDateInstance(DateFormat.SHORT, JAJPJP), + "令和1/5/1"), + Arguments.of(DateFormat.getDateInstance(DateFormat.SHORT, JCAL), + "令和1/5/1") + ); + } + + @ParameterizedTest + @MethodSource("gannen") + void testGannenFormat(DateFormat df, String expected) { + assertEquals(expected, df.format(c.getTime())); + } + + @ParameterizedTest + @MethodSource("gannen") + void testGannenParse(DateFormat df, String formatted) throws ParseException { + assertEquals(c.getTime(), df.parse(formatted)); + } +} diff --git a/test/jdk/java/util/Calendar/JapaneseEraNameTest.java b/test/jdk/java/util/Calendar/JapaneseEraNameTest.java deleted file mode 100644 index 11e35927adf..00000000000 --- a/test/jdk/java/util/Calendar/JapaneseEraNameTest.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8202088 8207152 8217609 8219890 - * @summary Test the localized Japanese new era name (May 1st. 2019-) - * is retrieved no matter CLDR provider contains the name or not. - * @modules jdk.localedata - * @run testng JapaneseEraNameTest - */ - -import static java.util.Calendar.*; -import static java.util.Locale.*; -import java.util.Calendar; -import java.util.Locale; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; - -@Test -public class JapaneseEraNameTest { - static final Calendar c = new Calendar.Builder() - .setCalendarType("japanese") - .setFields(ERA, 5, YEAR, 1, MONTH, MAY, DAY_OF_MONTH, 1) - .build(); - - @DataProvider(name="names") - Object[][] names() { - return new Object[][] { - // type, locale, name - { LONG, JAPAN, "\u4ee4\u548c" }, - { LONG, US, "Reiwa" }, - { LONG, CHINA, "\u4ee4\u548c" }, - { SHORT, JAPAN, "\u4ee4\u548c" }, - { SHORT, US, "Reiwa" }, - { SHORT, CHINA, "\u4ee4\u548c" }, - }; - } - - @Test(dataProvider="names") - public void testJapaneseNewEraName(int type, Locale locale, String expected) { - assertEquals(c.getDisplayName(ERA, type, locale), expected); - } -} From db7af2b3c3bd63f17f7952e815ebafb5dd8486ab Mon Sep 17 00:00:00 2001 From: Koushik Thirupattur Date: Thu, 12 Jun 2025 19:31:15 +0000 Subject: [PATCH 033/213] 8349550: Improve SASL random usage Reviewed-by: mullan --- src/java.base/share/classes/module-info.java | 1 + .../com/sun/security/sasl/CramMD5Server.java | 13 +++++++++---- .../com/sun/security/sasl/digest/DigestMD5Base.java | 13 +++++++------ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index fe043dadab5..43d148a3428 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -318,6 +318,7 @@ exports sun.security.internal.spec to jdk.crypto.cryptoki; exports sun.security.jca to + java.security.sasl, java.smartcardio, jdk.crypto.cryptoki, jdk.naming.dns; diff --git a/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Server.java b/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Server.java index 42a0409920c..b3dda2c869c 100644 --- a/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Server.java +++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/CramMD5Server.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,13 @@ package com.sun.security.sasl; +import sun.security.jca.JCAUtil; + import java.io.IOException; import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; import java.util.logging.Level; import java.util.Map; -import java.util.Random; import javax.security.sasl.*; import javax.security.auth.callback.*; @@ -52,6 +54,10 @@ * @author Rosanna Lee */ final class CramMD5Server extends CramMD5Base implements SaslServer { + + /* SecureRandom instance to generate random digits used in challenge */ + private static final SecureRandom SECURE_RANDOM = JCAUtil.getDefSecureRandom(); + private String fqdn; private byte[] challengeData = null; private String authzid; @@ -113,8 +119,7 @@ public byte[] evaluateResponse(byte[] responseData) } // Generate challenge {random, timestamp, fqdn} - Random random = new Random(); - long rand = random.nextLong(); + long rand = SECURE_RANDOM.nextLong(); long timestamp = System.currentTimeMillis(); StringBuilder sb = new StringBuilder(); diff --git a/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java b/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java index 535c11b4f0c..567c7171116 100644 --- a/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java +++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/digest/DigestMD5Base.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,10 @@ import java.util.Arrays; import java.util.List; import java.util.logging.Level; -import java.util.Random; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.InvalidKeyException; +import java.security.SecureRandom; import java.security.spec.KeySpec; import java.security.spec.InvalidKeySpecException; import java.security.InvalidAlgorithmParameterException; @@ -59,6 +59,7 @@ import javax.security.sasl.*; import com.sun.security.sasl.util.AbstractSaslImpl; +import sun.security.jca.JCAUtil; /** * Utility class for DIGEST-MD5 mechanism. Provides utility methods @@ -132,6 +133,9 @@ abstract class DigestMD5Base extends AbstractSaslImpl { protected static final byte[] EMPTY_BYTE_ARRAY = new byte[0]; + /* SecureRandom instance to generate nonce */ + private static final SecureRandom SECURE_RANDOM = JCAUtil.getDefSecureRandom(); + /* ------------------- Variable Fields ----------------------- */ /* Used to track progress of authentication; step numbers from RFC 2831 */ @@ -269,7 +273,6 @@ public Object getNegotiatedProperty(String propName) { * is slightly faster and a more compact representation of the same info. * @return A non-null byte array containing the nonce value for the * digest challenge or response. - * Could use SecureRandom to be more secure but it is very slow. */ /** This array maps the characters to their 6 bit values */ @@ -293,10 +296,8 @@ public Object getNegotiatedProperty(String propName) { protected static final byte[] generateNonce() { - // SecureRandom random = new SecureRandom(); - Random random = new Random(); byte[] randomData = new byte[RAW_NONCE_SIZE]; - random.nextBytes(randomData); + SECURE_RANDOM.nextBytes(randomData); byte[] nonce = new byte[ENCODED_NONCE_SIZE]; From 66535fe26da27dfaf0940bd70deb30942f7d0cdc Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 12 Jun 2025 20:06:19 +0000 Subject: [PATCH 034/213] 8358701: Remove misleading javax.management.remote API doc wording about JMX spec, and historic link to JMXMP Reviewed-by: alanb, sspitsyn --- .../javax/management/remote/package-info.java | 36 +++++-------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/src/java.management/share/classes/javax/management/remote/package-info.java b/src/java.management/share/classes/javax/management/remote/package-info.java index d198030c302..046cc8cd570 100644 --- a/src/java.management/share/classes/javax/management/remote/package-info.java +++ b/src/java.management/share/classes/javax/management/remote/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,9 @@ *

Interfaces for remote access to * JMX MBean servers. * This package defines the essential interfaces for making a JMX - * MBean server manageable remotely. The specification of this - * functionality is completed by Part III of the - * - * JMX Specification, version 1.4

+ * MBean server manageable remotely.

* - *

The JMX specification defines the notion of connectors. + *

JMX defines the notion of connectors. * A connector is attached to a JMX API MBean server and makes it * accessible to remote Java clients. The client end of a * connector exports essentially the same interface as the MBean @@ -41,32 +38,17 @@ * interface.

* *

A connector makes an MBean server remotely accessible through - * a given protocol. The JMX Remote API allows the use of different - * type of connectors: + * a given protocol. * - *

    + *
      *
    • The JMX Remote API defines a standard connector, * the RMI Connector, which provides remote access to an - * MBeanServer through RMI. + * MBeanServer through RMI. * - *
    • The JMX Remote API also defines an optional connector called - * JMXMP Connector implementing the JMX Message Protocol - * (JMXMP). As it is optional, it is not part of this bundle (see - * note below). - * - *
    • User-defined connector protocols are also possible using the + *
    • Other connector protocols are also possible using the * {@link javax.management.remote.JMXConnectorFactory - * JMXConnectorFactory} and, optionally, the Generic Connector - * (not part of this bundle, see note below). - *
    - * - *

    Note: the optional packages implementing - * the optional part of the JMX Remote API - * are not included in the Java SE Platform - * but are available from the JMX Remote API - * - * Reference Implementation.

    - * + * JMXConnectorFactory}. + *
* *

Connector addresses

* From 0dd7c69b9e4307e6e8f290b84828f6de8a79e644 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 12 Jun 2025 20:21:50 +0000 Subject: [PATCH 035/213] 8357286: (bf) Remove obsolete instanceof checks in CharBuffer.append Reviewed-by: alanb --- .../java/nio/Direct-X-Buffer.java.template | 35 +++++++------------ .../java/nio/Heap-X-Buffer.java.template | 34 +++++++----------- 2 files changed, 25 insertions(+), 44 deletions(-) diff --git a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index 580109a2eb0..12bc0103d1b 100644 --- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template @@ -430,8 +430,13 @@ class Direct$Type$Buffer$RW$$BO$ #if[rw] private static final int APPEND_BUF_SIZE = 1024; +#end[rw] + + public $Type$Buffer append(CharSequence csq, int start, int end) { +#if[rw] + if (csq == null) + return super.append(csq, start, end); - private $Type$Buffer appendChars(CharSequence csq, int start, int end) { Objects.checkFromToIndex(start, end, csq.length()); int pos = position(); @@ -448,13 +453,7 @@ class Direct$Type$Buffer$RW$$BO$ if (count > buf.length) count = buf.length; - if (csq instanceof String str) { - str.getChars(start, start + count, buf, 0); - } else if (csq instanceof StringBuilder sb) { - sb.getChars(start, start + count, buf, 0); - } else if (csq instanceof StringBuffer sb) { - sb.getChars(start, start + count, buf, 0); - } + csq.getChars(start, start + count, buf, 0); putArray(index, buf, 0, count); @@ -465,27 +464,19 @@ class Direct$Type$Buffer$RW$$BO$ position(pos + length); return this; - } -#end[rw] - public $Type$Buffer append(CharSequence csq) { -#if[rw] - if (csq instanceof StringBuilder) - return appendChars(csq, 0, csq.length()); - - return super.append(csq); #else[rw] throw new ReadOnlyBufferException(); #end[rw] } - - public $Type$Buffer append(CharSequence csq, int start, int end) { + + public $Type$Buffer append(CharSequence csq) { #if[rw] - if (csq instanceof String || csq instanceof StringBuffer || - csq instanceof StringBuilder) - return appendChars(csq, start, end); + // See comment regarding StringBuilder on HeapBuffer.append. + if (csq instanceof StringBuilder) + return append(csq, 0, csq.length()); - return super.append(csq, start, end); + return super.append(csq); #else[rw] throw new ReadOnlyBufferException(); #end[rw] diff --git a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template index 9dc46716119..ce21a997963 100644 --- a/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Heap-X-Buffer.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -290,7 +290,11 @@ class Heap$Type$Buffer$RW$ // or the full sequence of chars is being appended, copying the chars to // an intermedite String in StringBuilder::toString is avoided. // - private $Type$Buffer appendChars(CharSequence csq, int start, int end) { + public $Type$Buffer append(CharSequence csq, int start, int end) { +#if[rw] + if (csq == null) + return super.append(csq, start, end); + checkSession(); Objects.checkFromToIndex(start, end, csq.length()); @@ -302,37 +306,23 @@ class Heap$Type$Buffer$RW$ if (length > rem) throw new BufferOverflowException(); - if (csq instanceof String str) { - str.getChars(start, end, hb, ix(pos)); - } else if (csq instanceof StringBuilder sb) { - sb.getChars(start, end, hb, ix(pos)); - } else if (csq instanceof StringBuffer sb) { - sb.getChars(start, end, hb, ix(pos)); - } + csq.getChars(start, end, hb, ix(pos)); position(pos + length); return this; - } - - public $Type$Buffer append(CharSequence csq) { -#if[rw] - if (csq instanceof StringBuilder) - return appendChars(csq, 0, csq.length()); - - return super.append(csq); #else[rw] throw new ReadOnlyBufferException(); #end[rw] } - public $Type$Buffer append(CharSequence csq, int start, int end) { + public $Type$Buffer append(CharSequence csq) { #if[rw] - if (csq instanceof String || csq instanceof StringBuffer || - csq instanceof StringBuilder) - return appendChars(csq, start, end); + // See comment regarding StringBuilder on method append() above. + if (csq instanceof StringBuilder) + return append(csq, 0, csq.length()); - return super.append(csq, start, end); + return super.append(csq); #else[rw] throw new ReadOnlyBufferException(); #end[rw] From 523a4efe1ce2231edd7019043a49f7bf0a0f6aef Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 12 Jun 2025 20:23:28 +0000 Subject: [PATCH 036/213] 8358970: CounterMonitorMBean.getDerivedGaugeTimeStamp() JavaDoc incorrectly documents null Reviewed-by: sspitsyn, lmesnik --- .../classes/javax/management/monitor/CounterMonitorMBean.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.management/share/classes/javax/management/monitor/CounterMonitorMBean.java b/src/java.management/share/classes/javax/management/monitor/CounterMonitorMBean.java index 6e6b3ee99e0..dbf8dd73ea7 100644 --- a/src/java.management/share/classes/javax/management/monitor/CounterMonitorMBean.java +++ b/src/java.management/share/classes/javax/management/monitor/CounterMonitorMBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,7 +97,7 @@ public interface CounterMonitorMBean extends MonitorMBean { * * @param object the MBean for which the derived gauge timestamp is to be returned * @return The derived gauge timestamp for the specified MBean if this MBean - * is in the set of observed MBeans, or null otherwise. + * is in the set of observed MBeans, or 0 otherwise. * */ public long getDerivedGaugeTimeStamp(ObjectName object); From 991097b7bf08cc1a4ceedb0c555b12948ae71885 Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Fri, 13 Jun 2025 01:05:44 +0000 Subject: [PATCH 037/213] 8315066: Add unsigned bounds and known bits to TypeInt/Long Co-authored-by: Emanuel Peter Reviewed-by: epeter, kvn, jbhateja --- src/hotspot/share/opto/castnode.cpp | 6 +- src/hotspot/share/opto/compile.cpp | 4 +- src/hotspot/share/opto/compile.hpp | 4 +- src/hotspot/share/opto/graphKit.cpp | 4 +- src/hotspot/share/opto/ifnode.cpp | 3 +- src/hotspot/share/opto/rangeinference.cpp | 1081 +++++++++++++++++ src/hotspot/share/opto/rangeinference.hpp | 198 +++ src/hotspot/share/opto/type.cpp | 716 ++++------- src/hotspot/share/opto/type.hpp | 330 +++-- .../share/utilities/count_leading_zeros.hpp | 6 +- src/hotspot/share/utilities/intn_t.hpp | 166 +++ .../gtest/opto/test_rangeinference.cpp | 214 ++++ test/hotspot/gtest/utilities/test_intn_t.cpp | 70 ++ 13 files changed, 2239 insertions(+), 563 deletions(-) create mode 100644 src/hotspot/share/opto/rangeinference.cpp create mode 100644 src/hotspot/share/opto/rangeinference.hpp create mode 100644 src/hotspot/share/utilities/intn_t.hpp create mode 100644 test/hotspot/gtest/opto/test_rangeinference.cpp create mode 100644 test/hotspot/gtest/utilities/test_intn_t.cpp diff --git a/src/hotspot/share/opto/castnode.cpp b/src/hotspot/share/opto/castnode.cpp index 6b3058d94f6..b835950dfdb 100644 --- a/src/hotspot/share/opto/castnode.cpp +++ b/src/hotspot/share/opto/castnode.cpp @@ -498,7 +498,11 @@ Node* ConstraintCastNode::make_cast_for_type(Node* c, Node* in, const Type* type Node* ConstraintCastNode::optimize_integer_cast(PhaseGVN* phase, BasicType bt) { PhaseIterGVN *igvn = phase->is_IterGVN(); - const TypeInteger* this_type = this->type()->is_integer(bt); + const TypeInteger* this_type = this->type()->isa_integer(bt); + if (this_type == nullptr) { + return nullptr; + } + Node* z = in(1); const TypeInteger* rx = nullptr; const TypeInteger* ry = nullptr; diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index a5023408cdf..fb42ba4c9af 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -4521,7 +4521,9 @@ Node* Compile::conv_I2X_index(PhaseGVN* phase, Node* idx, const TypeInt* sizetyp // number. (The prior range check has ensured this.) // This assertion is used by ConvI2LNode::Ideal. int index_max = max_jint - 1; // array size is max_jint, index is one less - if (sizetype != nullptr) index_max = sizetype->_hi - 1; + if (sizetype != nullptr && sizetype->_hi > 0) { + index_max = sizetype->_hi - 1; + } const TypeInt* iidxtype = TypeInt::make(0, index_max, Type::WidenMax); idx = constrained_convI2L(phase, idx, iidxtype, ctrl); #endif diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 9b6d8db05b0..678b05a8517 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -928,8 +928,8 @@ class Compile : public Phase { bool copy_node_notes_to(Node* dest, Node* source); // Workhorse function to sort out the blocked Node_Notes array: - inline Node_Notes* locate_node_notes(GrowableArray* arr, - int idx, bool can_grow = false); + Node_Notes* locate_node_notes(GrowableArray* arr, + int idx, bool can_grow = false); void grow_node_notes(GrowableArray* arr, int grow_by); diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 20feca26ede..828dff29b55 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -3853,7 +3853,9 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) if (tilen != nullptr && tilen->_lo < 0) { // Add a manual constraint to a positive range. Cf. array_element_address. jint size_max = fast_size_limit; - if (size_max > tilen->_hi) size_max = tilen->_hi; + if (size_max > tilen->_hi && tilen->_hi >= 0) { + size_max = tilen->_hi; + } const TypeInt* tlcon = TypeInt::make(0, size_max, Type::WidenMin); // Only do a narrow I2L conversion if the range check passed. diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 8d810e4202f..fb048264071 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -1046,8 +1046,7 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f if (failtype != nullptr) { const TypeInt* type2 = filtered_int_type(igvn, n, fail); if (type2 != nullptr) { - failtype = failtype->join(type2)->is_int(); - if (failtype->empty()) { + if (failtype->filter(type2) == Type::TOP) { // previous if determines the result of this if so // replace Bool with constant igvn->replace_input_of(this, 1, igvn->intcon(success->_con)); diff --git a/src/hotspot/share/opto/rangeinference.cpp b/src/hotspot/share/opto/rangeinference.cpp new file mode 100644 index 00000000000..40b9da4bde5 --- /dev/null +++ b/src/hotspot/share/opto/rangeinference.cpp @@ -0,0 +1,1081 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "opto/rangeinference.hpp" +#include "opto/type.hpp" +#include "utilities/intn_t.hpp" +#include "utilities/tuple.hpp" + +// If the cardinality of a TypeInt is below this threshold, use min widen, see +// TypeIntPrototype::normalize_widen +constexpr juint SMALL_TYPEINT_THRESHOLD = 3; + +// This represents the result of an iterative calculation +template +class AdjustResult { +public: + bool _progress; // whether there is progress compared to the last iteration + bool _present; // whether the result is empty, typically due to the calculation arriving at contradiction + T _result; + + bool empty() const { + return !_present; + } + + static AdjustResult make_empty() { + return {true, false, {}}; + } +}; + +// This is the result of canonicalizing a simple interval (see TypeInt at +// type.hpp) +template +class SimpleCanonicalResult { + static_assert(U(-1) > U(0), "bit info should be unsigned"); +public: + const bool _present; // whether this is an empty set + const RangeInt _bounds; // The bounds must be in the same half of the integer domain (see TypeInt) + const KnownBits _bits; + + SimpleCanonicalResult(bool present, const RangeInt& bounds, const KnownBits& bits) + : _present(present), _bounds(bounds), _bits(bits) { + if (!present) { + return; + } + // Do some verification + assert(bits.is_satisfied_by(bounds._lo) && bits.is_satisfied_by(bounds._hi), "must be canonical"); + // 0b1000... + constexpr U mid_point = (std::numeric_limits::max() >> 1) + U(1); + assert((bounds._lo < mid_point) == (bounds._hi < mid_point), "must be a simple interval, see Lemma 4"); + } + + bool empty() const { + return !_present; + } + + static SimpleCanonicalResult make_empty() { + return SimpleCanonicalResult(false, {}, {}); + } +}; + +// Find the minimum value that is not less than lo and satisfies bits. If there +// does not exist one such number, the calculation will return a value < lo. +// +// Formally, this function tries to find the minimum value that is not less +// than lo and satisfies bits, assuming such value exists. The cases where such +// value does not exists automatically follows. +// +// If there exists a value not less than lo and satisfies bits, then this +// function will always find one such value. The converse is also true, that is +// if this function finds a value not less than lo and satisfies bits, then it +// must trivially be the case that there exists one such value. As a result, +// the negation of those statements are also equivalent, there does not exists +// a value not less than lo and satisfies bits if and only if this function +// does not return one such value. +// +// In practice, since the algorithm always ensures that the returned value +// satisfies bits, we only need to check if it is not less than lo. +// +// Here, we view a number in binary as a bit string. As a result, the first +// bit refers to the highest bit (the MSB), the last bit refers to the lowest +// bit (the LSB), a bit comes before (being higher than) another if it is more +// significant, and a bit comes after (being lower than) another if it is less +// significant. For a value n with w bits, we denote n[0] the first (highest) +// bit of n, n[1] the second bit, ..., n[w - 1] the last (lowest) bit of n. +template +static U adjust_lo(U lo, const KnownBits& bits) { + // Violation of lo with respects to bits + // E.g: lo = 1100 + // zeros = 0100 + // ones = 1001 + // zero_violation = 0100, i.e the second bit should be zero, but it is 1 in + // lo. Similarly, one_violation = 0001, i.e the last bit should be one, but + // it is 0 in lo. These make lo not satisfy the bit constraints, which + // results in us having to find the smallest value that satisfies bits. + U zero_violation = lo & bits._zeros; + U one_violation = ~lo & bits._ones; + if (zero_violation == one_violation) { + // This means lo does not violate bits, it is the result + assert(zero_violation == U(0), ""); + return lo; + } + + /* + 1. Intuition: + Call r the lowest value not smaller than lo that satisfies bits, consider the + first bit in r that is different from the corresponding bit in lo: + - Since r is larger than lo the bit must be 0 in lo and 1 in r + - Since r must satisify bits the bit must be 0 in zeros + - Since r should be the smallest value, this bit should be the lowest one + possible + + E.g: 1 2 3 4 5 6 + lo = 1 0 0 1 1 0 + x = 1 0 1 0 1 0 + y = 0 1 1 1 1 1 + x would be larger than lo since the first different bit is the 3rd one, + while y is smaller than lo because the first different bit is the 1st bit. + Next, consider: + x1 = 1 0 1 0 1 0 + x2 = 1 0 0 1 1 1 + Both x1 and x2 are larger than lo, but x1 > x2 since its first different + bit from lo is the 3rd one, while with x2 it is the 7th one. As a result, + if both x1 and x2 satisfy bits, x2 would be closer to our true result. + + 2. Formality: + + Call r the smallest value not smaller than lo that satisfies bits. Since lo + does not satisfy bits, lo < r (2.1) + + Call i the largest bit index such that: + + - lo[x] satisfies bits for 0 <= x < i (2.2) + - zeros[i] = 0 (2.3) + - lo[i] = 0 (2.4) + + Consider v: + + - v[x] = lo[x], for 0 <= x < i (2.5) + - v[i] = 1 (2.6) + - v[x] = ones[x], for x > i (2.7) + + We will prove that v == r. + + a. Firstly, we prove that r <= v: + + a.1. lo < v, since: + lo[x] == v[x], for 0 <= x < i (according to 2.5) + lo[i] < v[i] (according to 2.4 and 2.6, lo[i] == 0 < v[i] == 1) + bits at x > i have lower significance, and are thus irrelevant + + a.2. v satisfies bits, because: + v[x] satisfies bits for 0 <= x < i (according to 2.2 and 2.5) + v[i] satisfies bits: + According to 2.3 and 2.6, zeros[i] == 0 and v[i] == 1, v[i] does not violate + bits, which means v[i] satisfies bits + v[x] satisfies bits for x > i: + Assume bits is not contradictory, we cannot have: + ones[x] == 1, v[x] == 0 (according to 2.7, v[x] == ones[x]) + zeros[x] == 1, v[x] == 1 (according to 2.7, ones[x] == v[x] == 1, which means + bits is contradictory) + + From a.1 and a.2, v > lo and v satisfies bits. Which means r <= v since r is the + smallest such value. + + b. Secondly, from r <= v, we prove that r == v. Suppose the contradiction r < v: + + Since r < v, there must be a bit position j that: + + r[j] == 0 (2.b.1) + v[j] == 1 (2.b.2) + r[x] == v[x], for x < j (2.b.3) + + b.1. If j < i + This means that: + r[j] == 0 (according to 2.b.1) + lo[j] == 1 (according to 2.b.2 and 2.5, lo[j] == v[j] == 1 because j < i) + r[x] == lo[x], for x < j (according to 2.b.3 and 2.5, lo[x] == v[x] == r[x] with x < j < i) + bits at x > j have lower significance, and are thus irrelevant + + Which leads to r < lo, which contradicts that lo < r (acording to 2.1) + + b.2. If j == i + Since r > lo (according to 2.1), there must exist a bit index k such that: + + r[k] == 1 (2.b.2.1) + lo[k] == 0 (2.b.2.2) + r[x] == lo[x], for x < k (2.b.2.3) + + Then, since we have: + r[x] == v[x], for x < i (according to 2.b.3) + v[x] == lo[x], for x < i (according to 2.5) + r[i] == 0 (according to 2.b.1 because i == j) + lo[i] == 0 (according to 2.4) + + this leads to: r[x] == lo[x], for x <= i + while r[k] == 1 != lo[k] == 0, we can conclude that k > i + + However, since: + lo[x] satisfies bits for 0 <= x < k: + According to 2.b.2.3, lo[x] == r[x] and r satisfies bits + zeros[k] == 0 (according to 2.b.2.1, r[k] == 1 and r satisfies bits) + lo[k] == 0 (according to 2.b.2.2) + + This contradicts the assumption that i is the largest bit index satisfying such conditions. + + b.3. If j > i + ones[j] == v[j] (according to 2.7 since j > i) + v[j] == 1 (according to 2.b.2) + r[j] == 0 (according to 2.b.1) + + This means that r[j] == 0 and ones[j] == 1, this contradicts the assumption that r + satisfies bits. + + All cases lead to contradictions, which mean r < v is incorrect, which means that + r == v, which means the value v having the above form is the lowest value not smaller + than lo that satisfies bits. + + 3. Conclusion + Our objective now is to find the largest value i that satisfies: + - lo[x] satisfies bits for 0 <= x < i (3.1) + - zeros[i] = 0 (3.2) + - lo[i] = 0 (3.3) + */ + + // The algorithm depends on whether the first violation violates zeros or + // ones. If it violates zeros, we have the bit being 1 in zero_violation and + // 0 in one_violation. Since all higher bits are 0 in zero_violation and + // one_violation, we have zero_violation > one_violation. Similarly, if the + // first violation violates ones, we have zero_violation < one_violation. + if (zero_violation < one_violation) { + // This means that the first bit that does not satisfy the bit requirement + // is a 0 that should be a 1. Obviously, since the bit at that position in + // ones is 1, the same bit in zeros is 0. + // + // From section 3 above, we know i is the largest bit index such that: + // - lo[x] satisfies bits for 0 <= x < i (3.1) + // - zeros[i] = 0 (3.2) + // - lo[i] = 0 (3.3) + // + // For the given i, we know that lo satisfies all bits before i, hence (3.1) + // holds. Further, lo[i] = 0 (3.3), and we have a one violation at i, hence + // zero[i] = 0 (3.2). Any smaller i would not be the largest possible such + // index. Any larger i would violate (3.1), since lo[i] does not satisfy bits. + // As a result, the first violation is the bit i we are looking for. + // + // E.g: 1 2 3 4 5 6 7 8 + // lo = 1 1 0 0 0 1 1 0 + // zeros = 0 0 1 0 0 1 0 0 + // ones = 0 1 0 1 0 0 1 0 + // 1-vio = 0 0 0 1 0 0 0 0 + // 0-vio = 0 0 0 0 0 1 0 0 + // Since the result must have the 4th bit set, it must be at least: + // 1 1 0 1 0 0 0 0 + // This value must satisfy zeros, because all bits before the 4th bit have + // already satisfied zeros, and all bits after the 4th bit are all 0 now. + // Just OR this value with ones to obtain the final result. + + // first_violation is the position of the violation counting from the + // highest bit down (0-based), since i == 4, first_violation == 3 + juint first_violation = count_leading_zeros(one_violation); + // 1 0 0 0 0 0 0 0 + constexpr U highest_bit = (std::numeric_limits::max() >> 1) + U(1); + // This is the bit at which we want to change the bit 0 in lo to a 1, and + // all bits after to zero. This is similar to an operation that aligns lo + // up to the next multiple of this modulo. + // 0 0 0 1 0 0 0 0 + U alignment = highest_bit >> first_violation; + // This is the first value which have the violated bit being 1, which means + // that the result should not be smaller than this. + // This is a standard operation to align a value up to the next multiple of + // a certain power of 2. Since alignment is a power of 2, -alignment is a + // value having all the bits being 1 upto the location of the bit in + // alignment (in the example, -alignment = 11110000). As a result, + // lo & -alignment set all bits after the bit in alignment to 0, which is + // equivalent to rounding lo down to a multiple of alignment. To round lo + // up to the next multiple of alignment, we add alignment to the rounded + // down value. + // Note that this computation cannot overflow as the bit in lo that is at + // the same position as the only bit 1 in alignment must be 0. As a result, + // this operation just set that bit to 1 and set all the bits after to 0. + // We now have: + // - new_lo[x] = lo[x], for 0 <= x < i (2.5) + // - new_lo[i] = 1 (2.6) + // - new_lo[x] = 0, for x > i (not yet 2.7) + // 1 1 0 1 0 0 0 0 + U new_lo = (lo & -alignment) + alignment; + // Note that there exists no value x not larger than i such that + // new_lo[x] == 0 and ones[x] == 1. This is because all bits of lo before i + // should satisfy bits, and new_lo[i] == 1. As a result, doing + // new_lo |= bits.ones will give us a value such that: + // - new_lo[x] = lo[x], for 0 <= x < i (2.5) + // - new_lo[i] = 1 (2.6) + // - new_lo[x] = ones[x], for x > i (2.7) + // This is the result we are looking for. + // 1 1 0 1 0 0 1 0 + new_lo |= bits._ones; + // Note that in this case, new_lo is always a valid answer. That is, it is + // a value not less than lo and satisfies bits. + assert(lo < new_lo, "the result must be valid"); + return new_lo; + } else { + assert(zero_violation > one_violation, "remaining case"); + // This means that the first bit that does not satisfy the bit requirement + // is a 1 that should be a 0. + // + // From section 3 above, we know i is the largest bit index such that: + // - lo[x] satisfies bits for 0 <= x < i (3.1) + // - zeros[i] = 0 (3.2) + // - lo[i] = 0 (3.3) + // + // We know that lo satisfies all bits before first_violation, hence (3.1) + // holds. However, first_violation is not the value i we are looking for + // because lo[first_violation] == 1. We can also see that any larger value + // of i would violate (3.1) since lo[first_violation] does not satisfy + // bits. As a result, we should find the last index x upto first_violation + // such that lo[x] == zeros[x] == 0. That value of x would be the value of + // i we are looking for. + // + // E.g: 1 2 3 4 5 6 7 8 + // lo = 1 0 0 0 1 1 1 0 + // zeros = 0 0 0 1 0 1 0 0 + // ones = 1 0 0 0 0 0 1 1 + // 1-vio = 0 0 0 0 0 0 0 1 + // 0-vio = 0 0 0 0 0 1 0 0 + // The first violation is the 6th bit, which should be 0. We want to flip + // it to 0. However, since we must obtain a value larger than lo, we must + // find an earlier bit that can be flipped from 0 to 1. The 5th cannot be + // the bit we are looking for, because it is already 1, the 4th bit also + // cannot be, because it must be 0. As a result, the last bit we can flip, + // which is the first different bit between the result and lo must be the + // 3rd bit. As a result, the result must not be smaller than: + // 1 0 1 0 0 0 0 0 + // This one satisfies zeros so we can use the logic in the previous case, + // just OR with ones to obtain the final result, which is: + // 1 0 1 0 0 0 1 1 + + juint first_violation = count_leading_zeros(zero_violation); + // This masks out all bits after the first violation + // 1 1 1 1 1 0 0 0 + U find_mask = ~(std::numeric_limits::max() >> first_violation); + // We want to find the last index x upto first_violation such that + // lo[x] == zeros[x] == 0. + // We start with all bits where lo[x] == zeros[x] == 0: + // 0 1 1 0 0 0 0 1 + U neither = ~(lo | bits._zeros); + // Now let us find all the bit indices x upto first_violation such that + // lo[x] == zeros[x] == 0. The last one of these bits must be at index i. + // 0 1 1 0 0 0 0 0 + U neither_upto_first_violation = neither & find_mask; + // We now want to select the last one of these candidates, which is exactly + // the last index x upto first_violation such that lo[x] == zeros[x] == 0. + // This would be the value i we are looking for. + // Similar to the other case, we want to obtain the value with only the bit + // i set, this is equivalent to extracting the last set bit of + // neither_upto_first_violation, do it directly without going through i. + // The formula x & (-x) will give us the last set bit of an integer x + // (please see the x86 instruction blsi). + // In our example, i == 2 + // 0 0 1 0 0 0 0 0 + U alignment = neither_upto_first_violation & (-neither_upto_first_violation); + // Set the bit of lo at i and unset all the bits after, this is the + // smallest value that satisfies bits._zeros. Similar to the above case, + // this is similar to aligning lo up to the next multiple of alignment. + // Also similar to the above case, this computation cannot overflow. + // We now have: + // - new_lo[x] = lo[x], for 0 <= x < i (2.5) + // - new_lo[i] = 1 (2.6) + // - new_lo[x] = 0, for x > i (not yet 2.7) + // 1 0 1 0 0 0 0 0 + U new_lo = (lo & -alignment) + alignment; + // Note that there exists no value x not larger than i such that + // new_lo[x] == 0 and ones[x] == 1. This is because all bits of lo before i + // should satisfy bits, and new_lo[i] == 1. As a result, doing + // new_lo |= bits.ones will give us a value such that: + // - new_lo[x] = lo[x], for 0 <= x < i (2.5) + // - new_lo[i] = 1 (2.6) + // - new_lo[x] = ones[x], for x > i (2.7) + // This is the result we are looking for. + // 1 0 1 0 0 0 1 1 + new_lo |= bits._ones; + // Note that formally, this function assumes that there exists a value not + // smaller than lo and satisfies bits. This implies the existence of the + // index i satisfies (3.1-3.3), which means that + // neither_upto_first_violation != 0. The converse is + // also true, if neither_upto_first_violation != 0, then an index i + // satisfies (3.1-3.3) exists, which implies the existence of a value not + // smaller than lo and satisfies bits. As a result, the negation of those + // statements are equivalent. neither_upto_first_violation == 0 if and only + // if there does not exists a value not smaller than lo and satisfies bits. + // In this case, alignment == 0 and new_lo == bits._ones. We know that, if + // the assumption of this function holds, we return a value satisfying + // bits, and if the assumption of this function does not hold, the returned + // value would be bits._ones, which also satisfies bits. As a result, this + // function always returns a value satisfying bits, regardless whether if + // the assumption of this function holds. In conclusion, the caller only + // needs to check lo <= new_lo to find the cases where there exists no + // value not smaller than lo and satisfies bits (see the overview of the + // function). + assert(lo < new_lo || new_lo == bits._ones, "invalid result must be bits._ones"); + return new_lo; + } +} + +// Try to tighten the bound constraints from the known bit information. I.e, we +// find the smallest value not smaller than lo, as well as the largest value +// not larger than hi both of which satisfy bits +// E.g: lo = 0010, hi = 1001 +// zeros = 0011 +// ones = 0000 +// -> 4-aligned +// +// 0 1 2 3 4 5 6 7 8 9 10 +// 0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 +// bits: ok . . . ok . . . ok . . +// bounds: lo hi +// adjust: --------> lo hi <--- +template +static AdjustResult> +adjust_unsigned_bounds_from_bits(const RangeInt& bounds, const KnownBits& bits) { + U new_lo = adjust_lo(bounds._lo, bits); + if (new_lo < bounds._lo) { + // This means we wrapped around, which means no value not less than lo + // satisfies bits + return AdjustResult>::make_empty(); + } + + // We need to find the largest value not larger than hi that satisfies bits + // One possible method is to do similar to adjust_lo, just with the other + // direction + // However, we can observe that if v satisfies {bits._zeros, bits._ones}, + // then ~v would satisfy {bits._ones, bits._zeros}. Combine with the fact + // that bitwise-not is a strictly decreasing function, if new_hi is the + // largest value not larger than hi that satisfies {bits._zeros, bits._ones}, + // then ~new_hi is the smallest value not smaller than ~hi that satisfies + // {bits._ones, bits._zeros}. + // + // Proof: + // Calling h the smallest value not smaller than ~hi that satisfies + // {bits._ones, bits._zeros}. + // + // 1. Since h satisfies {bits._ones, bits._zeros}, ~h satisfies + // {bits._zeros, bits._ones}. Assume the contradiction ~h does not satisfy + // {bits._zeros, bits._ones}, There can be 2 cases: + // 1.1. There is a bit in ~h that is 0 where the corresponding bit in ones + // is 1. This implies the corresponding bit in h is 1. But this is + // contradictory since h satisfies {bits._ones, bits._zeros}. + // 1.2. There is a bit in ~h that is 1 where the corresponding bit in zeros + // is 1. Similarly, this leads to contradiction because h needs to + // satisfy {bits._ones, bits._zeros}. + // + // 2. Assume there is a value k that is larger than ~h such that k is not + // larger than hi, i.e. ~h < k <= hi, and k satisfies {bits._zeros, bits._ones}. + // As a result, ~k would satisfy {bits._ones, bits._zeros}. And since bitwise-not + // is a strictly decreasing function, given ~h < k <= hi, we have h > ~k >= ~hi. + // This contradicts the assumption that h is the smallest value not smaller than + // ~hi and satisfies {bits._ones, bits._zeros}. + // + // As a result, ~h is the largest value not larger than hi that satisfies + // bits (QED). + U h = adjust_lo(~bounds._hi, {bits._ones, bits._zeros}); + if (h < ~bounds._hi) { + return AdjustResult>::make_empty(); + } + + U new_hi = ~h; + bool progress = (new_lo != bounds._lo) || (new_hi != bounds._hi); + bool present = new_lo <= new_hi; + return {progress, present, {new_lo, new_hi}}; +} + +// Try to tighten the known bit constraints from the bound information by +// extracting the common prefix of lo and hi and combining with the current +// bit constraints +// E.g: lo = 010011 +// hi = 010100, +// then all values in [lo, hi] would be +// 010*** +template +static AdjustResult> +adjust_bits_from_unsigned_bounds(const KnownBits& bits, const RangeInt& bounds) { + // Find the mask to filter the common prefix, all values between bounds._lo + // and bounds._hi should share this common prefix in terms of bits + U mismatch = bounds._lo ^ bounds._hi; + // Find the first mismatch, all bits before it are the same in bounds._lo and + // bounds._hi + U match_mask = mismatch == U(0) ? std::numeric_limits::max() + : ~(std::numeric_limits::max() >> count_leading_zeros(mismatch)); + // match_mask & bounds._lo is the common prefix, extract zeros and ones from + // it + U common_prefix_zeros = match_mask & ~bounds._lo; + assert(common_prefix_zeros == (match_mask & ~bounds._hi), ""); + U new_zeros = bits._zeros | common_prefix_zeros; + + U common_prefix_ones = match_mask & bounds._lo; + assert(common_prefix_ones == (match_mask & bounds._hi), ""); + U new_ones = bits._ones | common_prefix_ones; + + bool progress = (new_zeros != bits._zeros) || (new_ones != bits._ones); + bool present = ((new_zeros & new_ones) == U(0)); + return {progress, present, {new_zeros, new_ones}}; +} + +// Try to tighten both the bounds and the bits at the same time. +// Iteratively tighten one using the other until no progress is made. +// This function converges because at each iteration, some bits that are unknown +// are made known. As there are at most 64 bits, the number of iterations should +// not be larger than 64. +// This function is called simple because it deals with a simple intervals (see +// TypeInt at type.hpp). +template +static SimpleCanonicalResult +canonicalize_constraints_simple(const RangeInt& bounds, const KnownBits& bits) { + assert((bounds._lo ^ bounds._hi) < (std::numeric_limits::max() >> 1) + U(1), "bounds must be a simple interval"); + + AdjustResult> canonicalized_bits = adjust_bits_from_unsigned_bounds(bits, bounds); + if (canonicalized_bits.empty()) { + return SimpleCanonicalResult::make_empty(); + } + AdjustResult> canonicalized_bounds{true, true, bounds}; + // Since bits are derived from bounds in the previous iteration and vice + // versa, if one does not show progress, the other will also not show + // progress, so we terminate early + while (true) { + canonicalized_bounds = adjust_unsigned_bounds_from_bits(canonicalized_bounds._result, canonicalized_bits._result); + if (!canonicalized_bounds._progress || canonicalized_bounds.empty()) { + return SimpleCanonicalResult(canonicalized_bounds._present, canonicalized_bounds._result, canonicalized_bits._result); + } + canonicalized_bits = adjust_bits_from_unsigned_bounds(canonicalized_bits._result, canonicalized_bounds._result); + if (!canonicalized_bits._progress || canonicalized_bits.empty()) { + return SimpleCanonicalResult(canonicalized_bits._present, canonicalized_bounds._result, canonicalized_bits._result); + } + } +} + +// Tighten all constraints of a TypeIntPrototype to its canonical form. +// i.e the result represents the same set as the input, each bound belongs to +// the set and for each bit position that is not constrained, there exists 2 +// values with the bit value at that position being set and unset, respectively, +// such that both belong to the set represented by the constraints. +template +typename TypeIntPrototype::CanonicalizedTypeIntPrototype +TypeIntPrototype::canonicalize_constraints() const { + RangeInt srange = _srange; + RangeInt urange = _urange; + // Trivial contradictions + if (srange._lo > srange._hi || + urange._lo > urange._hi || + (_bits._zeros & _bits._ones) != U(0)) { + return CanonicalizedTypeIntPrototype::make_empty(); + } + + // We try to make [srange._lo, S(urange._hi)] and + // [S(urange._lo), srange._hi] be both simple intervals (as defined in + // TypeInt at type.hpp) + if (S(urange._lo) > S(urange._hi)) { + // This means that S(urange._lo) >= 0 and S(urange._hi) < 0 because here we + // know that U(urange._lo) <= U(urange._hi) + if (S(urange._hi) < srange._lo) { + // This means that there should be no element in the interval + // [min_S, S(urange._hi)], tighten urange._hi to max_S + // Signed: + // min_S----uhi---------lo---------0--------ulo==========hi----max_S + // Unsigned: + // 0--------ulo==========hi----max_S min_S-----uhi---------lo--------- + urange._hi = U(std::numeric_limits::max()); + } else if (S(urange._lo) > srange._hi) { + // This means that there should be no element in the interval + // [S(urange._lo), max_S], tighten urange._lo to min_S + // Signed: + // min_S----lo=========uhi---------0--------hi----------ulo----max_S + // Unsigned: + // 0--------hi----------ulo----max_S min_S----lo=========uhi--------- + urange._lo = U(std::numeric_limits::min()); + } + } + + // Now [srange._lo, S(urange._hi)] and [S(urange._lo), srange._hi] are both + // simple intervals (as defined in TypeInt at type.hpp), we process them + // separately and combine the results + if (S(urange._lo) <= S(urange._hi)) { + // The 2 simple intervals should be tightened to the same result + urange._lo = U(MAX2(S(urange._lo), srange._lo)); + urange._hi = U(MIN2(S(urange._hi), srange._hi)); + if (urange._lo > urange._hi || S(urange._lo) > S(urange._hi)) { + return CanonicalizedTypeIntPrototype::make_empty(); + } + + auto type = canonicalize_constraints_simple(urange, _bits); + return {type._present, {{S(type._bounds._lo), S(type._bounds._hi)}, + type._bounds, type._bits}}; + } + + // The 2 simple intervals can be tightened into 2 separate results + auto neg_type = canonicalize_constraints_simple({U(srange._lo), urange._hi}, _bits); + auto pos_type = canonicalize_constraints_simple({urange._lo, U(srange._hi)}, _bits); + + if (neg_type.empty() && pos_type.empty()) { + return CanonicalizedTypeIntPrototype::make_empty(); + } else if (neg_type.empty()) { + return {true, {{S(pos_type._bounds._lo), S(pos_type._bounds._hi)}, + pos_type._bounds, pos_type._bits}}; + } else if (pos_type.empty()) { + return {true, {{S(neg_type._bounds._lo), S(neg_type._bounds._hi)}, + neg_type._bounds, neg_type._bits}}; + } else { + return {true, {{S(neg_type._bounds._lo), S(pos_type._bounds._hi)}, + {pos_type._bounds._lo, neg_type._bounds._hi}, + {neg_type._bits._zeros & pos_type._bits._zeros, neg_type._bits._ones & pos_type._bits._ones}}}; + } +} + +template +int TypeIntPrototype::normalize_widen(int widen) const { + // Certain normalizations keep us sane when comparing types. + // The 'SMALL_TYPEINT_THRESHOLD' covers constants and also CC and its relatives. + if (TypeIntHelper::cardinality_from_bounds(_srange, _urange) <= U(SMALL_TYPEINT_THRESHOLD)) { + return Type::WidenMin; + } + if (_srange._lo == std::numeric_limits::min() && _srange._hi == std::numeric_limits::max() && + _urange._lo == std::numeric_limits::min() && _urange._hi == std::numeric_limits::max() && + _bits._zeros == U(0) && _bits._ones == U(0)) { + // bottom type + return Type::WidenMax; + } + return widen; +} + +#ifdef ASSERT +template +bool TypeIntPrototype::contains(S v) const { + U u(v); + return v >= _srange._lo && v <= _srange._hi && + u >= _urange._lo && u <= _urange._hi && + _bits.is_satisfied_by(u); +} + +// Verify that this set representation is canonical +template +void TypeIntPrototype::verify_constraints() const { + // Assert that the bounds cannot be further tightened + assert(contains(_srange._lo) && contains(_srange._hi) && + contains(S(_urange._lo)) && contains(S(_urange._hi)), ""); + + // Assert that the bits cannot be further tightened + if (U(_srange._lo) == _urange._lo) { + assert(!adjust_bits_from_unsigned_bounds(_bits, _urange)._progress, ""); + } else { + RangeInt neg_range{U(_srange._lo), _urange._hi}; + auto neg_bits = adjust_bits_from_unsigned_bounds(_bits, neg_range); + assert(neg_bits._present, ""); + assert(!adjust_unsigned_bounds_from_bits(neg_range, neg_bits._result)._progress, ""); + + RangeInt pos_range{_urange._lo, U(_srange._hi)}; + auto pos_bits = adjust_bits_from_unsigned_bounds(_bits, pos_range); + assert(pos_bits._present, ""); + assert(!adjust_unsigned_bounds_from_bits(pos_range, pos_bits._result)._progress, ""); + + assert((neg_bits._result._zeros & pos_bits._result._zeros) == _bits._zeros && + (neg_bits._result._ones & pos_bits._result._ones) == _bits._ones, ""); + } +} +#endif // ASSERT + +template class TypeIntPrototype; +template class TypeIntPrototype; +template class TypeIntPrototype, uintn_t<1>>; +template class TypeIntPrototype, uintn_t<2>>; +template class TypeIntPrototype, uintn_t<3>>; +template class TypeIntPrototype, uintn_t<4>>; + +// Compute the meet of 2 types. When dual is true, the subset relation in CT is +// reversed. This means that the result of 2 CTs would be the intersection of +// them if dual is true, and be the union of them if dual is false. The subset +// relation in the Type hierarchy is still the same, however. E.g. the result +// of 1 CT and Type::BOTTOM would always be Type::BOTTOM, and the result of 1 +// CT and Type::TOP would always be the CT instance itself. +template +const Type* TypeIntHelper::int_type_xmeet(const CT* i1, const Type* t2) { + // Perform a fast test for common case; meeting the same types together. + if (i1 == t2 || t2 == Type::TOP) { + return i1; + } + const CT* i2 = t2->try_cast(); + if (i2 != nullptr) { + assert(i1->_is_dual == i2->_is_dual, "must have the same duality"); + using S = std::remove_const_t; + using U = std::remove_const_t; + + if (!i1->_is_dual) { + // meet (a.k.a union) + return CT::make_or_top(TypeIntPrototype{{MIN2(i1->_lo, i2->_lo), MAX2(i1->_hi, i2->_hi)}, + {MIN2(i1->_ulo, i2->_ulo), MAX2(i1->_uhi, i2->_uhi)}, + {i1->_bits._zeros & i2->_bits._zeros, i1->_bits._ones & i2->_bits._ones}}, + MAX2(i1->_widen, i2->_widen), false); + } else { + // join (a.k.a intersection) + return CT::make_or_top(TypeIntPrototype{{MAX2(i1->_lo, i2->_lo), MIN2(i1->_hi, i2->_hi)}, + {MAX2(i1->_ulo, i2->_ulo), MIN2(i1->_uhi, i2->_uhi)}, + {i1->_bits._zeros | i2->_bits._zeros, i1->_bits._ones | i2->_bits._ones}}, + MIN2(i1->_widen, i2->_widen), true); + } + } + + assert(t2->base() != i1->base(), ""); + switch (t2->base()) { // Switch on original type + case Type::AnyPtr: // Mixing with oops happens when javac + case Type::RawPtr: // reuses local variables + case Type::OopPtr: + case Type::InstPtr: + case Type::AryPtr: + case Type::MetadataPtr: + case Type::KlassPtr: + case Type::InstKlassPtr: + case Type::AryKlassPtr: + case Type::NarrowOop: + case Type::NarrowKlass: + case Type::Int: + case Type::Long: + case Type::HalfFloatTop: + case Type::HalfFloatCon: + case Type::HalfFloatBot: + case Type::FloatTop: + case Type::FloatCon: + case Type::FloatBot: + case Type::DoubleTop: + case Type::DoubleCon: + case Type::DoubleBot: + case Type::Bottom: // Ye Olde Default + return Type::BOTTOM; + default: // All else is a mistake + i1->typerr(t2); + return nullptr; + } +} +template const Type* TypeIntHelper::int_type_xmeet(const TypeInt* i1, const Type* t2); +template const Type* TypeIntHelper::int_type_xmeet(const TypeLong* i1, const Type* t2); + +// Called in PhiNode::Value during CCP, monotically widen the value set, do so rigorously +// first, after WidenMax attempts, if the type has still not converged we speed up the +// convergence by abandoning the bounds +template +const Type* TypeIntHelper::int_type_widen(const CT* new_type, const CT* old_type, const CT* limit_type) { + using S = std::remove_const_t; + using U = std::remove_const_t; + + if (old_type == nullptr) { + return new_type; + } + + // If new guy is equal to old guy, no widening + if (int_type_is_equal(new_type, old_type)) { + return old_type; + } + + // If old guy contains new, then we probably widened too far & dropped to + // bottom. Return the wider fellow. + if (int_type_is_subset(old_type, new_type)) { + return old_type; + } + + // Neither contains each other, weird? + if (!int_type_is_subset(new_type, old_type)) { + return CT::TYPE_DOMAIN; + } + + // If old guy was a constant, do not bother + if (old_type->singleton()) { + return new_type; + } + + // If new guy contains old, then we widened + // If new guy is already wider than old, no widening + if (new_type->_widen > old_type->_widen) { + return new_type; + } + + if (new_type->_widen < Type::WidenMax) { + // Returned widened new guy + TypeIntPrototype prototype{{new_type->_lo, new_type->_hi}, {new_type->_ulo, new_type->_uhi}, new_type->_bits}; + return CT::make_or_top(prototype, new_type->_widen + 1); + } + + // Speed up the convergence by abandoning the bounds, there are only a couple of bits so + // they converge fast + S min = std::numeric_limits::min(); + S max = std::numeric_limits::max(); + U umin = std::numeric_limits::min(); + U umax = std::numeric_limits::max(); + U zeros = new_type->_bits._zeros; + U ones = new_type->_bits._ones; + if (limit_type != nullptr) { + min = limit_type->_lo; + max = limit_type->_hi; + umin = limit_type->_ulo; + umax = limit_type->_uhi; + zeros |= limit_type->_bits._zeros; + ones |= limit_type->_bits._ones; + } + TypeIntPrototype prototype{{min, max}, {umin, umax}, {zeros, ones}}; + return CT::make_or_top(prototype, Type::WidenMax); +} +template const Type* TypeIntHelper::int_type_widen(const TypeInt* new_type, const TypeInt* old_type, const TypeInt* limit_type); +template const Type* TypeIntHelper::int_type_widen(const TypeLong* new_type, const TypeLong* old_type, const TypeLong* limit_type); + +// Called by PhiNode::Value during GVN, monotonically narrow the value set, only +// narrow if the bits change or if the bounds are tightened enough to avoid +// slow convergence +template +const Type* TypeIntHelper::int_type_narrow(const CT* new_type, const CT* old_type) { + using S = decltype(CT::_lo); + using U = decltype(CT::_ulo); + + if (new_type->singleton() || old_type == nullptr) { + return new_type; + } + + // If new guy is equal to old guy, no narrowing + if (int_type_is_equal(new_type, old_type)) { + return old_type; + } + + // If old guy was maximum range, allow the narrowing + if (int_type_is_equal(old_type, CT::TYPE_DOMAIN)) { + return new_type; + } + + // Doesn't narrow; pretty weird + if (!int_type_is_subset(old_type, new_type)) { + return new_type; + } + + // Bits change + if (old_type->_bits._zeros != new_type->_bits._zeros || old_type->_bits._ones != new_type->_bits._ones) { + return new_type; + } + + // Only narrow if the range shrinks a lot + U oc = cardinality_from_bounds(RangeInt{old_type->_lo, old_type->_hi}, + RangeInt{old_type->_ulo, old_type->_uhi}); + U nc = cardinality_from_bounds(RangeInt{new_type->_lo, new_type->_hi}, + RangeInt{new_type->_ulo, new_type->_uhi}); + return (nc > (oc >> 1) + (SMALL_TYPEINT_THRESHOLD * 2)) ? old_type : new_type; +} +template const Type* TypeIntHelper::int_type_narrow(const TypeInt* new_type, const TypeInt* old_type); +template const Type* TypeIntHelper::int_type_narrow(const TypeLong* new_type, const TypeLong* old_type); + + +#ifndef PRODUCT +template +static const char* int_name_near(T origin, const char* xname, char* buf, size_t buf_size, T n) { + if (n < origin) { + if (n <= origin - 10000) { + return nullptr; + } + os::snprintf_checked(buf, buf_size, "%s-" INT32_FORMAT, xname, jint(origin - n)); + } else if (n > origin) { + if (n >= origin + 10000) { + return nullptr; + } + os::snprintf_checked(buf, buf_size, "%s+" INT32_FORMAT, xname, jint(n - origin)); + } else { + return xname; + } + return buf; +} + +const char* TypeIntHelper::intname(char* buf, size_t buf_size, jint n) { + const char* str = int_name_near(max_jint, "maxint", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + str = int_name_near(min_jint, "minint", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + os::snprintf_checked(buf, buf_size, INT32_FORMAT, n); + return buf; +} + +const char* TypeIntHelper::uintname(char* buf, size_t buf_size, juint n) { + const char* str = int_name_near(max_juint, "maxuint", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + str = int_name_near(max_jint, "maxint", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + os::snprintf_checked(buf, buf_size, UINT32_FORMAT"u", n); + return buf; +} + +const char* TypeIntHelper::longname(char* buf, size_t buf_size, jlong n) { + const char* str = int_name_near(max_jlong, "maxlong", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + str = int_name_near(min_jlong, "minlong", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + str = int_name_near(max_juint, "maxuint", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + str = int_name_near(max_jint, "maxint", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + str = int_name_near(min_jint, "minint", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + os::snprintf_checked(buf, buf_size, JLONG_FORMAT, n); + return buf; +} + +const char* TypeIntHelper::ulongname(char* buf, size_t buf_size, julong n) { + const char* str = int_name_near(max_julong, "maxulong", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + str = int_name_near(max_jlong, "maxlong", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + str = int_name_near(max_juint, "maxuint", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + str = int_name_near(max_jint, "maxint", buf, buf_size, n); + if (str != nullptr) { + return str; + } + + os::snprintf_checked(buf, buf_size, JULONG_FORMAT"u", n); + return buf; +} + +template +const char* TypeIntHelper::bitname(char* buf, size_t buf_size, U zeros, U ones) { + constexpr juint W = sizeof(U) * 8; + + if (buf_size < W + 1) { + return "#####"; + } + + for (juint i = 0; i < W; i++) { + U mask = U(1) << (W - 1 - i); + if ((zeros & mask) != 0) { + buf[i] = '0'; + } else if ((ones & mask) != 0) { + buf[i] = '1'; + } else { + buf[i] = '*'; + } + } + buf[W] = 0; + return buf; +} +template const char* TypeIntHelper::bitname(char* buf, size_t buf_size, juint zeros, juint ones); +template const char* TypeIntHelper::bitname(char* buf, size_t buf_size, julong zeros, julong ones); + +void TypeIntHelper::int_type_dump(const TypeInt* t, outputStream* st, bool verbose) { + char buf1[40], buf2[40], buf3[40], buf4[40], buf5[40]; + if (int_type_is_equal(t, TypeInt::INT)) { + st->print("int"); + } else if (t->is_con()) { + st->print("int:%s", intname(buf1, sizeof(buf1), t->get_con())); + } else if (int_type_is_equal(t, TypeInt::BOOL)) { + st->print("bool"); + } else if (int_type_is_equal(t, TypeInt::BYTE)) { + st->print("byte"); + } else if (int_type_is_equal(t, TypeInt::CHAR)) { + st->print("char"); + } else if (int_type_is_equal(t, TypeInt::SHORT)) { + st->print("short"); + } else { + if (verbose) { + st->print("int:%s..%s, %s..%s, %s", + intname(buf1, sizeof(buf1), t->_lo), intname(buf2, sizeof(buf2), t->_hi), + uintname(buf3, sizeof(buf3), t->_ulo), uintname(buf4, sizeof(buf4), t->_uhi), + bitname(buf5, sizeof(buf5), t->_bits._zeros, t->_bits._ones)); + } else { + if (t->_lo >= 0) { + if (t->_hi == max_jint) { + st->print("int:>=%s", intname(buf1, sizeof(buf1), t->_lo)); + } else { + st->print("int:%s..%s", intname(buf1, sizeof(buf1), t->_lo), intname(buf2, sizeof(buf2), t->_hi)); + } + } else if (t->_hi < 0) { + if (t->_lo == min_jint) { + st->print("int:<=%s", intname(buf1, sizeof(buf1), t->_hi)); + } else { + st->print("int:%s..%s", intname(buf1, sizeof(buf1), t->_lo), intname(buf2, sizeof(buf2), t->_hi)); + } + } else { + st->print("int:%s..%s, %s..%s", + intname(buf1, sizeof(buf1), t->_lo), intname(buf2, sizeof(buf2), t->_hi), + uintname(buf3, sizeof(buf3), t->_ulo), uintname(buf4, sizeof(buf4), t->_uhi)); + } + + } + } + + if (t->_widen > 0 && t != TypeInt::INT) { + st->print(", widen: %d", t->_widen); + } +} + +void TypeIntHelper::int_type_dump(const TypeLong* t, outputStream* st, bool verbose) { + char buf1[80], buf2[80], buf3[80], buf4[80], buf5[80]; + if (int_type_is_equal(t, TypeLong::LONG)) { + st->print("long"); + } else if (t->is_con()) { + st->print("long:%s", longname(buf1, sizeof(buf1), t->get_con())); + } else { + if (verbose) { + st->print("long:%s..%s, %s..%s, bits:%s", + longname(buf1, sizeof(buf1), t->_lo), longname(buf2,sizeof(buf2), t-> _hi), + ulongname(buf3, sizeof(buf3), t->_ulo), ulongname(buf4, sizeof(buf4), t->_uhi), + bitname(buf5, sizeof(buf5), t->_bits._zeros, t->_bits._ones)); + } else { + if (t->_lo >= 0) { + if (t->_hi == max_jint) { + st->print("long:>=%s", longname(buf1, sizeof(buf1), t->_lo)); + } else { + st->print("long:%s..%s", longname(buf1, sizeof(buf1), t->_lo), longname(buf2, sizeof(buf2), t->_hi)); + } + } else if (t->_hi < 0) { + if (t->_lo == min_jint) { + st->print("long:<=%s", longname(buf1, sizeof(buf1), t->_hi)); + } else { + st->print("long:%s..%s", longname(buf1, sizeof(buf1), t->_lo), longname(buf2, sizeof(buf2), t->_hi)); + } + } else { + st->print("long:%s..%s, %s..%s", + longname(buf1, sizeof(buf1), t->_lo), longname(buf2,sizeof(buf2), t-> _hi), + ulongname(buf3, sizeof(buf3), t->_ulo), ulongname(buf4, sizeof(buf4), t->_uhi)); + } + } + } + + if (t->_widen > 0 && t != TypeLong::LONG) { + st->print(", widen: %d", t->_widen); + } +} +#endif // PRODUCT diff --git a/src/hotspot/share/opto/rangeinference.hpp b/src/hotspot/share/opto/rangeinference.hpp new file mode 100644 index 00000000000..84891d5e311 --- /dev/null +++ b/src/hotspot/share/opto/rangeinference.hpp @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_OPTO_RANGEINFERENCE_HPP +#define SHARE_OPTO_RANGEINFERENCE_HPP + +#include "utilities/globalDefinitions.hpp" +#include + +class outputStream; +class Type; +class TypeInt; +class TypeLong; + +// A simple range in the signed or unsigned domain +template +class RangeInt { +public: + T _lo; + T _hi; +}; + +/** + * Bits that are known to be 0 or 1. A value v satisfies this constraint iff + * (v & zeros) == 0 && (v & ones) == ones. I.e, any bit that is 1 in zeros must + * be 0 in v, and any bit that is 1 in ones must be 1 in v. + * + * I.e, for each bit position from 0 to sizeof(U) - 1, the corresponding bits + * of zeros, ones and the allowed bit in v must follow: + * + * zeros ones allowed bits + * 0 0 0 or 1 + * 1 0 0 + * 0 1 1 + * 1 1 none (impossible state) + * + * E.g: + * zeros: 00110100 + * ones: 10000010 + * Then: 10001010 would satisfy the bit constraints + * while: 10011000 would not since the bit at the 4th position violates + * zeros and the bit at the 7th position violates ones + * + * A KnownBits is sane if there is no position at which a bit must be both set + * and unset at the same time. That is (zeros & ones) == 0. + */ +template +class KnownBits { + static_assert(U(-1) > U(0), "bit info should be unsigned"); + +public: + U _zeros; + U _ones; + + bool is_satisfied_by(U v) const { + return (v & _zeros) == U(0) && (v & _ones) == _ones; + } +}; + +// All the information needed to construct a TypeInt/TypeLong, the constraints +// here may be arbitrary and need to be canonicalized to construct a +// TypeInt/TypeLong +template +class TypeIntPrototype { +public: + static_assert(S(-1) < S(0), ""); + static_assert(U(-1) > U(0), ""); + static_assert(sizeof(S) == sizeof(U), ""); + + RangeInt _srange; + RangeInt _urange; + KnownBits _bits; + +private: + friend class TypeInt; + friend class TypeLong; + + template + friend void test_canonicalize_constraints_exhaustive(); + + template + friend void test_canonicalize_constraints_simple(); + + template + friend void test_canonicalize_constraints_random(); + + // A canonicalized version of a TypeIntPrototype, if the prototype represents + // an empty type, _present is false, otherwise, _data is canonical + class CanonicalizedTypeIntPrototype { + public: + bool _present; // whether this is an empty set + TypeIntPrototype _data; + + bool empty() const { + return !_present; + } + + static CanonicalizedTypeIntPrototype make_empty() { + return {false, {}}; + } + }; + + CanonicalizedTypeIntPrototype canonicalize_constraints() const; + int normalize_widen(int w) const; +#ifdef ASSERT + bool contains(S v) const; + void verify_constraints() const; +#endif // ASSERT +}; + +// Various helper functions for TypeInt/TypeLong operations +class TypeIntHelper { +public: + // Calculate the cardinality of a TypeInt/TypeLong ignoring the bits + // constraints, the return value is the cardinality minus 1 to not overflow + // with the bottom type + template + static U cardinality_from_bounds(const RangeInt& srange, const RangeInt& urange) { + static_assert(S(-1) < S(0), ""); + static_assert(U(-1) > U(0), ""); + static_assert(sizeof(S) == sizeof(U), ""); + + if (U(srange._lo) == urange._lo) { + // srange is the same as urange + assert(U(srange._hi) == urange._hi, ""); + // The cardinality is (hi - lo + 1), we return the result minus 1 + return urange._hi - urange._lo; + } + + // srange intersects with urange in 2 intervals [srange._lo, urange._hi] + // and [urange._lo, srange._hi] + // The cardinality is (uhi - lo + 1) + (hi - ulo + 1), we return the result + // minus 1 + return (urange._hi - U(srange._lo)) + (U(srange._hi) - urange._lo) + U(1); + } + + template + static const Type* int_type_xmeet(const CT* i1, const Type* t2); + + template + static bool int_type_is_equal(const CT* t1, const CT* t2) { + return t1->_lo == t2->_lo && t1->_hi == t2->_hi && + t1->_ulo == t2->_ulo && t1->_uhi == t2->_uhi && + t1->_bits._zeros == t2->_bits._zeros && t1->_bits._ones == t2->_bits._ones; + } + + template + static bool int_type_is_subset(const CT* super, const CT* sub) { + return super->_lo <= sub->_lo && super->_hi >= sub->_hi && + super->_ulo <= sub->_ulo && super->_uhi >= sub->_uhi && + // All bits that are known in super must also be known to be the same + // value in sub, &~ (and not) is the same as a set subtraction on bit + // sets + (super->_bits._zeros &~ sub->_bits._zeros) == 0 && (super->_bits._ones &~ sub->_bits._ones) == 0; + } + + template + static const Type* int_type_widen(const CT* new_type, const CT* old_type, const CT* limit_type); + + template + static const Type* int_type_narrow(const CT* new_type, const CT* old_type); + +#ifndef PRODUCT + static const char* intname(char* buf, size_t buf_size, jint n); + static const char* uintname(char* buf, size_t buf_size, juint n); + static const char* longname(char* buf, size_t buf_size, jlong n); + static const char* ulongname(char* buf, size_t buf_size, julong n); + + template + static const char* bitname(char* buf, size_t buf_size, U zeros, U ones); + + static void int_type_dump(const TypeInt* t, outputStream* st, bool verbose); + static void int_type_dump(const TypeLong* t, outputStream* st, bool verbose); +#endif // PRODUCT +}; + +#endif // SHARE_OPTO_RANGEINFERENCE_HPP diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 163f94ee959..050297db153 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -40,6 +40,7 @@ #include "opto/matcher.hpp" #include "opto/node.hpp" #include "opto/opcodes.hpp" +#include "opto/rangeinference.hpp" #include "opto/runtime.hpp" #include "opto/type.hpp" #include "utilities/checkedCast.hpp" @@ -428,7 +429,6 @@ int Type::uhash( const Type *const t ) { return (int)t->hash(); } -#define SMALLINT ((juint)3) // a value too insignificant to consider widening #define POSITIVE_INFINITE_F 0x7f800000 // hex representation for IEEE 754 single precision positive infinite #define POSITIVE_INFINITE_D 0x7ff0000000000000 // hex representation for IEEE 754 double precision positive infinite @@ -487,44 +487,47 @@ void Type::Initialize_shared(Compile* current) { TypeInt::MAX = TypeInt::make(max_jint); // Int MAX TypeInt::MIN = TypeInt::make(min_jint); // Int MIN - TypeInt::MINUS_1 = TypeInt::make(-1); // -1 - TypeInt::ZERO = TypeInt::make( 0); // 0 - TypeInt::ONE = TypeInt::make( 1); // 1 - TypeInt::BOOL = TypeInt::make(0,1, WidenMin); // 0 or 1, FALSE or TRUE. - TypeInt::CC = TypeInt::make(-1, 1, WidenMin); // -1, 0 or 1, condition codes - TypeInt::CC_LT = TypeInt::make(-1,-1, WidenMin); // == TypeInt::MINUS_1 - TypeInt::CC_GT = TypeInt::make( 1, 1, WidenMin); // == TypeInt::ONE - TypeInt::CC_EQ = TypeInt::make( 0, 0, WidenMin); // == TypeInt::ZERO - TypeInt::CC_LE = TypeInt::make(-1, 0, WidenMin); - TypeInt::CC_GE = TypeInt::make( 0, 1, WidenMin); // == TypeInt::BOOL - TypeInt::BYTE = TypeInt::make(-128,127, WidenMin); // Bytes - TypeInt::UBYTE = TypeInt::make(0, 255, WidenMin); // Unsigned Bytes - TypeInt::CHAR = TypeInt::make(0,65535, WidenMin); // Java chars - TypeInt::SHORT = TypeInt::make(-32768,32767, WidenMin); // Java shorts - TypeInt::POS = TypeInt::make(0,max_jint, WidenMin); // Non-neg values - TypeInt::POS1 = TypeInt::make(1,max_jint, WidenMin); // Positive values - TypeInt::INT = TypeInt::make(min_jint,max_jint, WidenMax); // 32-bit integers - TypeInt::SYMINT = TypeInt::make(-max_jint,max_jint,WidenMin); // symmetric range - TypeInt::TYPE_DOMAIN = TypeInt::INT; + TypeInt::MINUS_1 = TypeInt::make(-1); // -1 + TypeInt::ZERO = TypeInt::make( 0); // 0 + TypeInt::ONE = TypeInt::make( 1); // 1 + TypeInt::BOOL = TypeInt::make( 0, 1, WidenMin); // 0 or 1, FALSE or TRUE. + TypeInt::CC = TypeInt::make(-1, 1, WidenMin); // -1, 0 or 1, condition codes + TypeInt::CC_LT = TypeInt::make(-1,-1, WidenMin); // == TypeInt::MINUS_1 + TypeInt::CC_GT = TypeInt::make( 1, 1, WidenMin); // == TypeInt::ONE + TypeInt::CC_EQ = TypeInt::make( 0, 0, WidenMin); // == TypeInt::ZERO + TypeInt::CC_NE = TypeInt::make_or_top(TypeIntPrototype{{-1, 1}, {1, max_juint}, {0, 1}}, WidenMin)->is_int(); + TypeInt::CC_LE = TypeInt::make(-1, 0, WidenMin); + TypeInt::CC_GE = TypeInt::make( 0, 1, WidenMin); // == TypeInt::BOOL + TypeInt::BYTE = TypeInt::make(-128, 127, WidenMin); // Bytes + TypeInt::UBYTE = TypeInt::make(0, 255, WidenMin); // Unsigned Bytes + TypeInt::CHAR = TypeInt::make(0, 65535, WidenMin); // Java chars + TypeInt::SHORT = TypeInt::make(-32768, 32767, WidenMin); // Java shorts + TypeInt::NON_ZERO = TypeInt::make_or_top(TypeIntPrototype{{min_jint, max_jint}, {1, max_juint}, {0, 0}}, WidenMin)->is_int(); + TypeInt::POS = TypeInt::make(0, max_jint, WidenMin); // Non-neg values + TypeInt::POS1 = TypeInt::make(1, max_jint, WidenMin); // Positive values + TypeInt::INT = TypeInt::make(min_jint, max_jint, WidenMax); // 32-bit integers + TypeInt::SYMINT = TypeInt::make(-max_jint, max_jint, WidenMin); // symmetric range + TypeInt::TYPE_DOMAIN = TypeInt::INT; // CmpL is overloaded both as the bytecode computation returning - // a trinary (-1,0,+1) integer result AND as an efficient long + // a trinary (-1, 0, +1) integer result AND as an efficient long // compare returning optimizer ideal-type flags. - assert( TypeInt::CC_LT == TypeInt::MINUS_1, "types must match for CmpL to work" ); - assert( TypeInt::CC_GT == TypeInt::ONE, "types must match for CmpL to work" ); - assert( TypeInt::CC_EQ == TypeInt::ZERO, "types must match for CmpL to work" ); - assert( TypeInt::CC_GE == TypeInt::BOOL, "types must match for CmpL to work" ); - assert( (juint)(TypeInt::CC->_hi - TypeInt::CC->_lo) <= SMALLINT, "CC is truly small"); - - TypeLong::MAX = TypeLong::make(max_jlong); // Long MAX - TypeLong::MIN = TypeLong::make(min_jlong); // Long MIN - TypeLong::MINUS_1 = TypeLong::make(-1); // -1 - TypeLong::ZERO = TypeLong::make( 0); // 0 - TypeLong::ONE = TypeLong::make( 1); // 1 - TypeLong::POS = TypeLong::make(0,max_jlong, WidenMin); // Non-neg values - TypeLong::LONG = TypeLong::make(min_jlong,max_jlong,WidenMax); // 64-bit integers - TypeLong::INT = TypeLong::make((jlong)min_jint,(jlong)max_jint,WidenMin); - TypeLong::UINT = TypeLong::make(0,(jlong)max_juint,WidenMin); - TypeLong::TYPE_DOMAIN = TypeLong::LONG; + assert(TypeInt::CC_LT == TypeInt::MINUS_1, "types must match for CmpL to work" ); + assert(TypeInt::CC_GT == TypeInt::ONE, "types must match for CmpL to work" ); + assert(TypeInt::CC_EQ == TypeInt::ZERO, "types must match for CmpL to work" ); + assert(TypeInt::CC_GE == TypeInt::BOOL, "types must match for CmpL to work" ); + + TypeLong::MAX = TypeLong::make(max_jlong); // Long MAX + TypeLong::MIN = TypeLong::make(min_jlong); // Long MIN + TypeLong::MINUS_1 = TypeLong::make(-1); // -1 + TypeLong::ZERO = TypeLong::make( 0); // 0 + TypeLong::ONE = TypeLong::make( 1); // 1 + TypeLong::NON_ZERO = TypeLong::make_or_top(TypeIntPrototype{{min_jlong, max_jlong}, {1, max_julong}, {0, 0}}, WidenMin)->is_long(); + TypeLong::POS = TypeLong::make(0, max_jlong, WidenMin); // Non-neg values + TypeLong::NEG = TypeLong::make(min_jlong, -1, WidenMin); + TypeLong::LONG = TypeLong::make(min_jlong, max_jlong, WidenMax); // 64-bit integers + TypeLong::INT = TypeLong::make((jlong)min_jint, (jlong)max_jint,WidenMin); + TypeLong::UINT = TypeLong::make(0, (jlong)max_juint, WidenMin); + TypeLong::TYPE_DOMAIN = TypeLong::LONG; const Type **fboth =(const Type**)shared_type_arena->AmallocWords(2*sizeof(Type*)); fboth[0] = Type::CONTROL; @@ -1745,218 +1748,124 @@ const TypeInteger* TypeInteger::minus_1(BasicType bt) { //============================================================================= // Convenience common pre-built types. -const TypeInt *TypeInt::MAX; // INT_MAX -const TypeInt *TypeInt::MIN; // INT_MIN -const TypeInt *TypeInt::MINUS_1;// -1 -const TypeInt *TypeInt::ZERO; // 0 -const TypeInt *TypeInt::ONE; // 1 -const TypeInt *TypeInt::BOOL; // 0 or 1, FALSE or TRUE. -const TypeInt *TypeInt::CC; // -1,0 or 1, condition codes -const TypeInt *TypeInt::CC_LT; // [-1] == MINUS_1 -const TypeInt *TypeInt::CC_GT; // [1] == ONE -const TypeInt *TypeInt::CC_EQ; // [0] == ZERO -const TypeInt *TypeInt::CC_LE; // [-1,0] -const TypeInt *TypeInt::CC_GE; // [0,1] == BOOL (!) -const TypeInt *TypeInt::BYTE; // Bytes, -128 to 127 -const TypeInt *TypeInt::UBYTE; // Unsigned Bytes, 0 to 255 -const TypeInt *TypeInt::CHAR; // Java chars, 0-65535 -const TypeInt *TypeInt::SHORT; // Java shorts, -32768-32767 -const TypeInt *TypeInt::POS; // Positive 32-bit integers or zero -const TypeInt *TypeInt::POS1; // Positive 32-bit integers -const TypeInt *TypeInt::INT; // 32-bit integers -const TypeInt *TypeInt::SYMINT; // symmetric range [-max_jint..max_jint] -const TypeInt *TypeInt::TYPE_DOMAIN; // alias for TypeInt::INT - -//------------------------------TypeInt---------------------------------------- -TypeInt::TypeInt( jint lo, jint hi, int w ) : TypeInteger(Int, w), _lo(lo), _hi(hi) { -} +const TypeInt* TypeInt::MAX; // INT_MAX +const TypeInt* TypeInt::MIN; // INT_MIN +const TypeInt* TypeInt::MINUS_1;// -1 +const TypeInt* TypeInt::ZERO; // 0 +const TypeInt* TypeInt::ONE; // 1 +const TypeInt* TypeInt::BOOL; // 0 or 1, FALSE or TRUE. +const TypeInt* TypeInt::CC; // -1,0 or 1, condition codes +const TypeInt* TypeInt::CC_LT; // [-1] == MINUS_1 +const TypeInt* TypeInt::CC_GT; // [1] == ONE +const TypeInt* TypeInt::CC_EQ; // [0] == ZERO +const TypeInt* TypeInt::CC_NE; +const TypeInt* TypeInt::CC_LE; // [-1,0] +const TypeInt* TypeInt::CC_GE; // [0,1] == BOOL (!) +const TypeInt* TypeInt::BYTE; // Bytes, -128 to 127 +const TypeInt* TypeInt::UBYTE; // Unsigned Bytes, 0 to 255 +const TypeInt* TypeInt::CHAR; // Java chars, 0-65535 +const TypeInt* TypeInt::SHORT; // Java shorts, -32768-32767 +const TypeInt* TypeInt::NON_ZERO; +const TypeInt* TypeInt::POS; // Positive 32-bit integers or zero +const TypeInt* TypeInt::POS1; // Positive 32-bit integers +const TypeInt* TypeInt::INT; // 32-bit integers +const TypeInt* TypeInt::SYMINT; // symmetric range [-max_jint..max_jint] +const TypeInt* TypeInt::TYPE_DOMAIN; // alias for TypeInt::INT -//------------------------------make------------------------------------------- -const TypeInt *TypeInt::make( jint lo ) { - return (TypeInt*)(new TypeInt(lo,lo,WidenMin))->hashcons(); +TypeInt::TypeInt(const TypeIntPrototype& t, int widen, bool dual) + : TypeInteger(Int, t.normalize_widen(widen), dual), _lo(t._srange._lo), _hi(t._srange._hi), + _ulo(t._urange._lo), _uhi(t._urange._hi), _bits(t._bits) { + DEBUG_ONLY(t.verify_constraints()); } -static int normalize_int_widen( jint lo, jint hi, int w ) { - // Certain normalizations keep us sane when comparing types. - // The 'SMALLINT' covers constants and also CC and its relatives. - if (lo <= hi) { - if (((juint)hi - lo) <= SMALLINT) w = Type::WidenMin; - if (((juint)hi - lo) >= max_juint) w = Type::WidenMax; // TypeInt::INT - } else { - if (((juint)lo - hi) <= SMALLINT) w = Type::WidenMin; - if (((juint)lo - hi) >= max_juint) w = Type::WidenMin; // dual TypeInt::INT +const Type* TypeInt::make_or_top(const TypeIntPrototype& t, int widen, bool dual) { + auto canonicalized_t = t.canonicalize_constraints(); + if (canonicalized_t.empty()) { + return dual ? Type::BOTTOM : Type::TOP; } - return w; + return (new TypeInt(canonicalized_t._data, widen, dual))->hashcons()->is_int(); } -const TypeInt *TypeInt::make( jint lo, jint hi, int w ) { - w = normalize_int_widen(lo, hi, w); - return (TypeInt*)(new TypeInt(lo,hi,w))->hashcons(); +const TypeInt* TypeInt::make(jint con) { + juint ucon = con; + return (new TypeInt(TypeIntPrototype{{con, con}, {ucon, ucon}, {~ucon, ucon}}, + WidenMin, false))->hashcons()->is_int(); } -//------------------------------meet------------------------------------------- -// Compute the MEET of two types. It returns a new Type representation object -// with reference count equal to the number of Types pointing at it. -// Caller should wrap a Types around it. -const Type *TypeInt::xmeet( const Type *t ) const { - // Perform a fast test for common case; meeting the same types together. - if( this == t ) return this; // Meeting same type? - - // Currently "this->_base" is a TypeInt - switch (t->base()) { // Switch on original type - case AnyPtr: // Mixing with oops happens when javac - case RawPtr: // reuses local variables - case OopPtr: - case InstPtr: - case AryPtr: - case MetadataPtr: - case KlassPtr: - case InstKlassPtr: - case AryKlassPtr: - case NarrowOop: - case NarrowKlass: - case Long: - case HalfFloatTop: - case HalfFloatCon: - case HalfFloatBot: - case FloatTop: - case FloatCon: - case FloatBot: - case DoubleTop: - case DoubleCon: - case DoubleBot: - case Bottom: // Ye Olde Default - return Type::BOTTOM; - default: // All else is a mistake - typerr(t); - case Top: // No change - return this; - case Int: // Int vs Int? - break; - } - - // Expand covered set - const TypeInt *r = t->is_int(); - return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ); +const TypeInt* TypeInt::make(jint lo, jint hi, int widen) { + assert(lo <= hi, "must be legal bounds"); + return make_or_top(TypeIntPrototype{{lo, hi}, {0, max_juint}, {0, 0}}, widen)->is_int(); } -//------------------------------xdual------------------------------------------ -// Dual: reverse hi & lo; flip widen -const Type *TypeInt::xdual() const { - int w = normalize_int_widen(_hi,_lo, WidenMax-_widen); - return new TypeInt(_hi,_lo,w); -} - -//------------------------------widen------------------------------------------ -// Only happens for optimistic top-down optimizations. -const Type *TypeInt::widen( const Type *old, const Type* limit ) const { - // Coming from TOP or such; no widening - if( old->base() != Int ) return this; - const TypeInt *ot = old->is_int(); - - // If new guy is equal to old guy, no widening - if( _lo == ot->_lo && _hi == ot->_hi ) - return old; - - // If new guy contains old, then we widened - if( _lo <= ot->_lo && _hi >= ot->_hi ) { - // New contains old - // If new guy is already wider than old, no widening - if( _widen > ot->_widen ) return this; - // If old guy was a constant, do not bother - if (ot->_lo == ot->_hi) return this; - // Now widen new guy. - // Check for widening too far - if (_widen == WidenMax) { - int max = max_jint; - int min = min_jint; - if (limit->isa_int()) { - max = limit->is_int()->_hi; - min = limit->is_int()->_lo; - } - if (min < _lo && _hi < max) { - // If neither endpoint is extremal yet, push out the endpoint - // which is closer to its respective limit. - if (_lo >= 0 || // easy common case - ((juint)_lo - min) >= ((juint)max - _hi)) { - // Try to widen to an unsigned range type of 31 bits: - return make(_lo, max, WidenMax); - } else { - return make(min, _hi, WidenMax); - } - } - return TypeInt::INT; - } - // Returned widened new guy - return make(_lo,_hi,_widen+1); - } - - // If old guy contains new, then we probably widened too far & dropped to - // bottom. Return the wider fellow. - if ( ot->_lo <= _lo && ot->_hi >= _hi ) - return old; +const Type* TypeInt::make_or_top(const TypeIntPrototype& t, int widen) { + return make_or_top(t, widen, false); +} - //fatal("Integer value range is not subset"); - //return this; - return TypeInt::INT; +bool TypeInt::contains(jint i) const { + assert(!_is_dual, "dual types should only be used for join calculation"); + juint u = i; + return i >= _lo && i <= _hi && + u >= _ulo && u <= _uhi && + _bits.is_satisfied_by(u); } -//------------------------------narrow--------------------------------------- -// Only happens for pessimistic optimizations. -const Type *TypeInt::narrow( const Type *old ) const { - if (_lo >= _hi) return this; // already narrow enough - if (old == nullptr) return this; - const TypeInt* ot = old->isa_int(); - if (ot == nullptr) return this; - jint olo = ot->_lo; - jint ohi = ot->_hi; +bool TypeInt::contains(const TypeInt* t) const { + assert(!_is_dual && !t->_is_dual, "dual types should only be used for join calculation"); + return TypeIntHelper::int_type_is_subset(this, t); +} - // If new guy is equal to old guy, no narrowing - if (_lo == olo && _hi == ohi) return old; +const Type* TypeInt::xmeet(const Type* t) const { + return TypeIntHelper::int_type_xmeet(this, t); +} - // If old guy was maximum range, allow the narrowing - if (olo == min_jint && ohi == max_jint) return this; +const Type* TypeInt::xdual() const { + return new TypeInt(TypeIntPrototype{{_lo, _hi}, {_ulo, _uhi}, _bits}, + _widen, !_is_dual); +} - if (_lo < olo || _hi > ohi) - return this; // doesn't narrow; pretty weird +const Type* TypeInt::widen(const Type* old, const Type* limit) const { + assert(!_is_dual, "dual types should only be used for join calculation"); + return TypeIntHelper::int_type_widen(this, old->isa_int(), limit->isa_int()); +} - // The new type narrows the old type, so look for a "death march". - // See comments on PhaseTransform::saturate. - juint nrange = (juint)_hi - _lo; - juint orange = (juint)ohi - olo; - if (nrange < max_juint - 1 && nrange > (orange >> 1) + (SMALLINT*2)) { - // Use the new type only if the range shrinks a lot. - // We do not want the optimizer computing 2^31 point by point. - return old; +const Type* TypeInt::narrow(const Type* old) const { + assert(!_is_dual, "dual types should only be used for join calculation"); + if (old == nullptr) { + return this; } - return this; + return TypeIntHelper::int_type_narrow(this, old->isa_int()); } //-----------------------------filter------------------------------------------ -const Type *TypeInt::filter_helper(const Type *kills, bool include_speculative) const { +const Type* TypeInt::filter_helper(const Type* kills, bool include_speculative) const { + assert(!_is_dual, "dual types should only be used for join calculation"); const TypeInt* ft = join_helper(kills, include_speculative)->isa_int(); - if (ft == nullptr || ft->empty()) + if (ft == nullptr) { return Type::TOP; // Canonical empty value + } + assert(!ft->_is_dual, "dual types should only be used for join calculation"); if (ft->_widen < this->_widen) { // Do not allow the value of kill->_widen to affect the outcome. // The widen bits must be allowed to run freely through the graph. - ft = TypeInt::make(ft->_lo, ft->_hi, this->_widen); + return (new TypeInt(TypeIntPrototype{{ft->_lo, ft->_hi}, {ft->_ulo, ft->_uhi}, ft->_bits}, + this->_widen, false))->hashcons(); } return ft; } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations -bool TypeInt::eq( const Type *t ) const { - const TypeInt *r = t->is_int(); // Handy access - return r->_lo == _lo && r->_hi == _hi && r->_widen == _widen; +bool TypeInt::eq(const Type* t) const { + const TypeInt* r = t->is_int(); + return TypeIntHelper::int_type_is_equal(this, r) && _widen == r->_widen && _is_dual == r->_is_dual; } //------------------------------hash------------------------------------------- // Type-specific hashing function. uint TypeInt::hash(void) const { - return (uint)_lo + (uint)_hi + (uint)_widen + (uint)Type::Int; + return (uint)_lo + (uint)_hi + (uint)_ulo + (uint)_uhi + + (uint)_bits._zeros + (uint)_bits._ones + (uint)_widen + (uint)_is_dual + (uint)Type::Int; } //------------------------------is_finite-------------------------------------- @@ -1965,267 +1874,126 @@ bool TypeInt::is_finite() const { return true; } -//------------------------------dump2------------------------------------------ -// Dump TypeInt -#ifndef PRODUCT -static const char* intname(char* buf, size_t buf_size, jint n) { - if (n == min_jint) - return "min"; - else if (n < min_jint + 10000) - os::snprintf_checked(buf, buf_size, "min+" INT32_FORMAT, n - min_jint); - else if (n == max_jint) - return "max"; - else if (n > max_jint - 10000) - os::snprintf_checked(buf, buf_size, "max-" INT32_FORMAT, max_jint - n); - else - os::snprintf_checked(buf, buf_size, INT32_FORMAT, n); - return buf; -} - -void TypeInt::dump2( Dict &d, uint depth, outputStream *st ) const { - char buf[40], buf2[40]; - if (_lo == min_jint && _hi == max_jint) - st->print("int"); - else if (is_con()) - st->print("int:%s", intname(buf, sizeof(buf), get_con())); - else if (_lo == BOOL->_lo && _hi == BOOL->_hi) - st->print("bool"); - else if (_lo == BYTE->_lo && _hi == BYTE->_hi) - st->print("byte"); - else if (_lo == CHAR->_lo && _hi == CHAR->_hi) - st->print("char"); - else if (_lo == SHORT->_lo && _hi == SHORT->_hi) - st->print("short"); - else if (_hi == max_jint) - st->print("int:>=%s", intname(buf, sizeof(buf), _lo)); - else if (_lo == min_jint) - st->print("int:<=%s", intname(buf, sizeof(buf), _hi)); - else - st->print("int:%s..%s", intname(buf, sizeof(buf), _lo), intname(buf2, sizeof(buf2), _hi)); - - if (_widen != 0 && this != TypeInt::INT) - st->print(":%.*s", _widen, "wwww"); -} -#endif - //------------------------------singleton-------------------------------------- // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants. bool TypeInt::singleton(void) const { - return _lo >= _hi; + return _lo == _hi; } bool TypeInt::empty(void) const { - return _lo > _hi; + return false; } //============================================================================= // Convenience common pre-built types. -const TypeLong *TypeLong::MAX; -const TypeLong *TypeLong::MIN; -const TypeLong *TypeLong::MINUS_1;// -1 -const TypeLong *TypeLong::ZERO; // 0 -const TypeLong *TypeLong::ONE; // 1 -const TypeLong *TypeLong::POS; // >=0 -const TypeLong *TypeLong::LONG; // 64-bit integers -const TypeLong *TypeLong::INT; // 32-bit subrange -const TypeLong *TypeLong::UINT; // 32-bit unsigned subrange -const TypeLong *TypeLong::TYPE_DOMAIN; // alias for TypeLong::LONG - -//------------------------------TypeLong--------------------------------------- -TypeLong::TypeLong(jlong lo, jlong hi, int w) : TypeInteger(Long, w), _lo(lo), _hi(hi) { -} +const TypeLong* TypeLong::MAX; +const TypeLong* TypeLong::MIN; +const TypeLong* TypeLong::MINUS_1;// -1 +const TypeLong* TypeLong::ZERO; // 0 +const TypeLong* TypeLong::ONE; // 1 +const TypeLong* TypeLong::NON_ZERO; +const TypeLong* TypeLong::POS; // >=0 +const TypeLong* TypeLong::NEG; +const TypeLong* TypeLong::LONG; // 64-bit integers +const TypeLong* TypeLong::INT; // 32-bit subrange +const TypeLong* TypeLong::UINT; // 32-bit unsigned subrange +const TypeLong* TypeLong::TYPE_DOMAIN; // alias for TypeLong::LONG -//------------------------------make------------------------------------------- -const TypeLong *TypeLong::make( jlong lo ) { - return (TypeLong*)(new TypeLong(lo,lo,WidenMin))->hashcons(); +TypeLong::TypeLong(const TypeIntPrototype& t, int widen, bool dual) + : TypeInteger(Long, t.normalize_widen(widen), dual), _lo(t._srange._lo), _hi(t._srange._hi), + _ulo(t._urange._lo), _uhi(t._urange._hi), _bits(t._bits) { + DEBUG_ONLY(t.verify_constraints()); } -static int normalize_long_widen( jlong lo, jlong hi, int w ) { - // Certain normalizations keep us sane when comparing types. - // The 'SMALLINT' covers constants. - if (lo <= hi) { - if (((julong)hi - lo) <= SMALLINT) w = Type::WidenMin; - if (((julong)hi - lo) >= max_julong) w = Type::WidenMax; // TypeLong::LONG - } else { - if (((julong)lo - hi) <= SMALLINT) w = Type::WidenMin; - if (((julong)lo - hi) >= max_julong) w = Type::WidenMin; // dual TypeLong::LONG +const Type* TypeLong::make_or_top(const TypeIntPrototype& t, int widen, bool dual) { + auto canonicalized_t = t.canonicalize_constraints(); + if (canonicalized_t.empty()) { + return dual ? Type::BOTTOM : Type::TOP; } - return w; + return (new TypeLong(canonicalized_t._data, widen, dual))->hashcons()->is_long(); } -const TypeLong *TypeLong::make( jlong lo, jlong hi, int w ) { - w = normalize_long_widen(lo, hi, w); - return (TypeLong*)(new TypeLong(lo,hi,w))->hashcons(); +const TypeLong* TypeLong::make(jlong con) { + julong ucon = con; + return (new TypeLong(TypeIntPrototype{{con, con}, {ucon, ucon}, {~ucon, ucon}}, + WidenMin, false))->hashcons()->is_long(); } - -//------------------------------meet------------------------------------------- -// Compute the MEET of two types. It returns a new Type representation object -// with reference count equal to the number of Types pointing at it. -// Caller should wrap a Types around it. -const Type *TypeLong::xmeet( const Type *t ) const { - // Perform a fast test for common case; meeting the same types together. - if( this == t ) return this; // Meeting same type? - - // Currently "this->_base" is a TypeLong - switch (t->base()) { // Switch on original type - case AnyPtr: // Mixing with oops happens when javac - case RawPtr: // reuses local variables - case OopPtr: - case InstPtr: - case AryPtr: - case MetadataPtr: - case KlassPtr: - case InstKlassPtr: - case AryKlassPtr: - case NarrowOop: - case NarrowKlass: - case Int: - case HalfFloatTop: - case HalfFloatCon: - case HalfFloatBot: - case FloatTop: - case FloatCon: - case FloatBot: - case DoubleTop: - case DoubleCon: - case DoubleBot: - case Bottom: // Ye Olde Default - return Type::BOTTOM; - default: // All else is a mistake - typerr(t); - case Top: // No change - return this; - case Long: // Long vs Long? - break; - } - - // Expand covered set - const TypeLong *r = t->is_long(); // Turn into a TypeLong - return make( MIN2(_lo,r->_lo), MAX2(_hi,r->_hi), MAX2(_widen,r->_widen) ); +const TypeLong* TypeLong::make(jlong lo, jlong hi, int widen) { + assert(lo <= hi, "must be legal bounds"); + return make_or_top(TypeIntPrototype{{lo, hi}, {0, max_julong}, {0, 0}}, widen)->is_long(); } -//------------------------------xdual------------------------------------------ -// Dual: reverse hi & lo; flip widen -const Type *TypeLong::xdual() const { - int w = normalize_long_widen(_hi,_lo, WidenMax-_widen); - return new TypeLong(_hi,_lo,w); -} - -//------------------------------widen------------------------------------------ -// Only happens for optimistic top-down optimizations. -const Type *TypeLong::widen( const Type *old, const Type* limit ) const { - // Coming from TOP or such; no widening - if( old->base() != Long ) return this; - const TypeLong *ot = old->is_long(); - - // If new guy is equal to old guy, no widening - if( _lo == ot->_lo && _hi == ot->_hi ) - return old; - - // If new guy contains old, then we widened - if( _lo <= ot->_lo && _hi >= ot->_hi ) { - // New contains old - // If new guy is already wider than old, no widening - if( _widen > ot->_widen ) return this; - // If old guy was a constant, do not bother - if (ot->_lo == ot->_hi) return this; - // Now widen new guy. - // Check for widening too far - if (_widen == WidenMax) { - jlong max = max_jlong; - jlong min = min_jlong; - if (limit->isa_long()) { - max = limit->is_long()->_hi; - min = limit->is_long()->_lo; - } - if (min < _lo && _hi < max) { - // If neither endpoint is extremal yet, push out the endpoint - // which is closer to its respective limit. - if (_lo >= 0 || // easy common case - ((julong)_lo - min) >= ((julong)max - _hi)) { - // Try to widen to an unsigned range type of 32/63 bits: - if (max >= max_juint && _hi < max_juint) - return make(_lo, max_juint, WidenMax); - else - return make(_lo, max, WidenMax); - } else { - return make(min, _hi, WidenMax); - } - } - return TypeLong::LONG; - } - // Returned widened new guy - return make(_lo,_hi,_widen+1); - } - - // If old guy contains new, then we probably widened too far & dropped to - // bottom. Return the wider fellow. - if ( ot->_lo <= _lo && ot->_hi >= _hi ) - return old; +const Type* TypeLong::make_or_top(const TypeIntPrototype& t, int widen) { + return make_or_top(t, widen, false); +} - // fatal("Long value range is not subset"); - // return this; - return TypeLong::LONG; +bool TypeLong::contains(jlong i) const { + assert(!_is_dual, "dual types should only be used for join calculation"); + julong u = i; + return i >= _lo && i <= _hi && + u >= _ulo && u <= _uhi && + _bits.is_satisfied_by(u); } -//------------------------------narrow---------------------------------------- -// Only happens for pessimistic optimizations. -const Type *TypeLong::narrow( const Type *old ) const { - if (_lo >= _hi) return this; // already narrow enough - if (old == nullptr) return this; - const TypeLong* ot = old->isa_long(); - if (ot == nullptr) return this; - jlong olo = ot->_lo; - jlong ohi = ot->_hi; +bool TypeLong::contains(const TypeLong* t) const { + assert(!_is_dual && !t->_is_dual, "dual types should only be used for join calculation"); + return TypeIntHelper::int_type_is_subset(this, t); +} - // If new guy is equal to old guy, no narrowing - if (_lo == olo && _hi == ohi) return old; +const Type* TypeLong::xmeet(const Type* t) const { + return TypeIntHelper::int_type_xmeet(this, t); +} - // If old guy was maximum range, allow the narrowing - if (olo == min_jlong && ohi == max_jlong) return this; +const Type* TypeLong::xdual() const { + return new TypeLong(TypeIntPrototype{{_lo, _hi}, {_ulo, _uhi}, _bits}, + _widen, !_is_dual); +} - if (_lo < olo || _hi > ohi) - return this; // doesn't narrow; pretty weird +const Type* TypeLong::widen(const Type* old, const Type* limit) const { + assert(!_is_dual, "dual types should only be used for join calculation"); + return TypeIntHelper::int_type_widen(this, old->isa_long(), limit->isa_long()); +} - // The new type narrows the old type, so look for a "death march". - // See comments on PhaseTransform::saturate. - julong nrange = (julong)_hi - _lo; - julong orange = (julong)ohi - olo; - if (nrange < max_julong - 1 && nrange > (orange >> 1) + (SMALLINT*2)) { - // Use the new type only if the range shrinks a lot. - // We do not want the optimizer computing 2^31 point by point. - return old; +const Type* TypeLong::narrow(const Type* old) const { + assert(!_is_dual, "dual types should only be used for join calculation"); + if (old == nullptr) { + return this; } - return this; + return TypeIntHelper::int_type_narrow(this, old->isa_long()); } //-----------------------------filter------------------------------------------ -const Type *TypeLong::filter_helper(const Type *kills, bool include_speculative) const { +const Type* TypeLong::filter_helper(const Type* kills, bool include_speculative) const { + assert(!_is_dual, "dual types should only be used for join calculation"); const TypeLong* ft = join_helper(kills, include_speculative)->isa_long(); - if (ft == nullptr || ft->empty()) + if (ft == nullptr) { return Type::TOP; // Canonical empty value + } + assert(!ft->_is_dual, "dual types should only be used for join calculation"); if (ft->_widen < this->_widen) { // Do not allow the value of kill->_widen to affect the outcome. // The widen bits must be allowed to run freely through the graph. - ft = TypeLong::make(ft->_lo, ft->_hi, this->_widen); + return (new TypeLong(TypeIntPrototype{{ft->_lo, ft->_hi}, {ft->_ulo, ft->_uhi}, ft->_bits}, + this->_widen, false))->hashcons(); } return ft; } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations -bool TypeLong::eq( const Type *t ) const { - const TypeLong *r = t->is_long(); // Handy access - return r->_lo == _lo && r->_hi == _hi && r->_widen == _widen; +bool TypeLong::eq(const Type* t) const { + const TypeLong* r = t->is_long(); + return TypeIntHelper::int_type_is_equal(this, r) && _widen == r->_widen && _is_dual == r->_is_dual; } //------------------------------hash------------------------------------------- // Type-specific hashing function. uint TypeLong::hash(void) const { - return (uint)_lo + (uint)_hi + (uint)_widen + (uint)Type::Long; + return (uint)_lo + (uint)_hi + (uint)_ulo + (uint)_uhi + + (uint)_bits._zeros + (uint)_bits._ones + (uint)_widen + (uint)_is_dual + (uint)Type::Long; } //------------------------------is_finite-------------------------------------- @@ -2234,72 +2002,36 @@ bool TypeLong::is_finite() const { return true; } -//------------------------------dump2------------------------------------------ -// Dump TypeLong -#ifndef PRODUCT -static const char* longnamenear(jlong x, const char* xname, char* buf, size_t buf_size, jlong n) { - if (n > x) { - if (n >= x + 10000) return nullptr; - os::snprintf_checked(buf, buf_size, "%s+" JLONG_FORMAT, xname, n - x); - } else if (n < x) { - if (n <= x - 10000) return nullptr; - os::snprintf_checked(buf, buf_size, "%s-" JLONG_FORMAT, xname, x - n); - } else { - return xname; - } - return buf; -} - -static const char* longname(char* buf, size_t buf_size, jlong n) { - const char* str; - if (n == min_jlong) - return "min"; - else if (n < min_jlong + 10000) - os::snprintf_checked(buf, buf_size, "min+" JLONG_FORMAT, n - min_jlong); - else if (n == max_jlong) - return "max"; - else if (n > max_jlong - 10000) - os::snprintf_checked(buf, buf_size, "max-" JLONG_FORMAT, max_jlong - n); - else if ((str = longnamenear(max_juint, "maxuint", buf, buf_size, n)) != nullptr) - return str; - else if ((str = longnamenear(max_jint, "maxint", buf, buf_size, n)) != nullptr) - return str; - else if ((str = longnamenear(min_jint, "minint", buf, buf_size, n)) != nullptr) - return str; - else - os::snprintf_checked(buf, buf_size, JLONG_FORMAT, n); - return buf; -} - -void TypeLong::dump2( Dict &d, uint depth, outputStream *st ) const { - char buf[80], buf2[80]; - if (_lo == min_jlong && _hi == max_jlong) - st->print("long"); - else if (is_con()) - st->print("long:%s", longname(buf, sizeof(buf), get_con())); - else if (_hi == max_jlong) - st->print("long:>=%s", longname(buf, sizeof(buf), _lo)); - else if (_lo == min_jlong) - st->print("long:<=%s", longname(buf, sizeof(buf), _hi)); - else - st->print("long:%s..%s", longname(buf, sizeof(buf), _lo), longname(buf2,sizeof(buf2), _hi)); - - if (_widen != 0 && this != TypeLong::LONG) - st->print(":%.*s", _widen, "wwww"); -} -#endif - //------------------------------singleton-------------------------------------- // TRUE if Type is a singleton type, FALSE otherwise. Singletons are simple // constants bool TypeLong::singleton(void) const { - return _lo >= _hi; + return _lo == _hi; } bool TypeLong::empty(void) const { - return _lo > _hi; + return false; +} + +//------------------------------dump2------------------------------------------ +#ifndef PRODUCT +void TypeInt::dump2(Dict& d, uint depth, outputStream* st) const { + TypeIntHelper::int_type_dump(this, st, false); +} + +void TypeInt::dump_verbose() const { + TypeIntHelper::int_type_dump(this, tty, true); } +void TypeLong::dump2(Dict& d, uint depth, outputStream* st) const { + TypeIntHelper::int_type_dump(this, st, false); +} + +void TypeLong::dump_verbose() const { + TypeIntHelper::int_type_dump(this, tty, true); +} +#endif + //============================================================================= // Convenience common pre-built types. const TypeTuple *TypeTuple::IFBOTH; // Return both arms of IF as reachable @@ -2551,10 +2283,15 @@ const Type *TypeAry::xmeet( const Type *t ) const { typerr(t); case Array: { // Meeting 2 arrays? - const TypeAry *a = t->is_ary(); + const TypeAry* a = t->is_ary(); + const Type* size = _size->xmeet(a->_size); + const TypeInt* isize = size->isa_int(); + if (isize == nullptr) { + assert(size == Type::TOP || size == Type::BOTTOM, ""); + return size; + } return TypeAry::make(_elem->meet_speculative(a->_elem), - _size->xmeet(a->_size)->is_int(), - _stable && a->_stable); + isize, _stable && a->_stable); } case Top: break; @@ -4984,10 +4721,12 @@ const TypeInt* TypeAryPtr::narrow_size_type(const TypeInt* size) const { chg = true; } // Negative length arrays will produce weird intermediate dead fast-path code - if (lo > hi) + if (lo > hi) { return TypeInt::ZERO; - if (!chg) + } + if (!chg) { return size; + } return TypeInt::make(lo, hi, Type::WidenMin); } @@ -5152,7 +4891,12 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { case AryPtr: { // Meeting 2 references? const TypeAryPtr *tap = t->is_aryptr(); int off = meet_offset(tap->offset()); - const TypeAry *tary = _ary->meet_speculative(tap->_ary)->is_ary(); + const Type* tm = _ary->meet_speculative(tap->_ary); + const TypeAry* tary = tm->isa_ary(); + if (tary == nullptr) { + assert(tm == Type::TOP || tm == Type::BOTTOM, ""); + return tm; + } PTR ptr = meet_ptr(tap->ptr()); int instance_id = meet_instance_id(tap->instance_id()); const TypePtr* speculative = xmeet_speculative(tap); diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 9c40e1ab3cd..f8f523563a0 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -26,6 +26,8 @@ #define SHARE_OPTO_TYPE_HPP #include "opto/adlcVMDeps.hpp" +#include "opto/compile.hpp" +#include "opto/rangeinference.hpp" #include "runtime/handles.hpp" // Portions of code courtesy of Clifford Click @@ -73,6 +75,9 @@ class TypeAryKlassPtr; class TypeMetadataPtr; class VerifyMeet; +template +class TypeIntPrototype; + //------------------------------Type------------------------------------------- // Basic Type object, represents a set of primitive Values. // Types are hash-cons'd into a private class dictionary, so only one of each @@ -284,6 +289,10 @@ class Type { virtual float getf() const; double getd() const; + // This has the same semantics as std::dynamic_cast(this) + template + const TypeClass* try_cast() const; + const TypeInt *is_int() const; const TypeInt *isa_int() const; // Returns null if not an Int const TypeInteger* is_integer(BasicType bt) const; @@ -594,7 +603,12 @@ class TypeD : public Type { class TypeInteger : public Type { protected: - TypeInteger(TYPES t, int w) : Type(t), _widen(w) {} + TypeInteger(TYPES t, int w, bool dual) : Type(t), _is_dual(dual), _widen(w) {} + + // Denote that a set is a dual set. + // Dual sets are only used to compute the join of 2 sets, and not used + // outside. + const bool _is_dual; public: const short _widen; // Limit on times we widen this sucker @@ -614,82 +628,240 @@ class TypeInteger : public Type { static const TypeInteger* minus_1(BasicType type); }; +/** + * Definition: + * + * A TypeInt represents a set of non-empty jint values. A jint v is an element + * of a TypeInt iff: + * + * v >= _lo && v <= _hi && + * juint(v) >= _ulo && juint(v) <= _uhi && + * _bits.is_satisfied_by(v) + * + * Multiple sets of parameters can represent the same set. + * E.g: consider 2 TypeInt t1, t2 + * + * t1._lo = 2, t1._hi = 7, t1._ulo = 0, t1._uhi = 5, t1._bits._zeros = 0x00000000, t1._bits._ones = 0x1 + * t2._lo = 3, t2._hi = 5, t2._ulo = 3, t2._uhi = 5, t2._bits._zeros = 0xFFFFFFF8, t2._bits._ones = 0x1 + * + * Then, t1 and t2 both represent the set {3, 5}. We can also see that the + * constraints of t2 are the tightest possible. I.e there exists no TypeInt t3 + * which also represents {3, 5} such that any of these would be true: + * + * 1) t3._lo > t2._lo + * 2) t3._hi < t2._hi + * 3) t3._ulo > t2._ulo + * 4) t3._uhi < t2._uhi + * 5) (t3._bits._zeros &~ t2._bis._zeros) != 0 + * 6) (t3._bits._ones &~ t2._bits._ones) != 0 + * + * The 5-th condition mean that the subtraction of the bitsets represented by + * t3._bits._zeros and t2._bits._zeros is not empty, which means that the + * bits in t3._bits._zeros is not a subset of those in t2._bits._zeros, the + * same applies to _bits._ones + * + * To simplify reasoning about the types in optimizations, we canonicalize + * every TypeInt to its tightest form, already at construction. E.g a TypeInt + * t with t._lo < 0 will definitely contain negative values. It also makes it + * trivial to determine if a TypeInt instance is a subset of another. + * + * Lemmas: + * + * 1. Since every TypeInt instance is non-empty and canonicalized, all the + * bounds must also be elements of such TypeInt. Or else, we can tighten the + * bounds by narrowing it by one, which contradicts the assumption of the + * TypeInt being canonical. + * + * 2. + * 2.1. _lo <= jint(_ulo) + * 2.2. _lo <= _hi + * 2.3. _lo <= jint(_uhi) + * 2.4. _ulo <= juint(_lo) + * 2.5. _ulo <= juint(_hi) + * 2.6. _ulo <= _uhi + * 2.7. _hi >= _lo + * 2.8. _hi >= jint(_ulo) + * 2.9. _hi >= jint(_uhi) + * 2.10. _uhi >= juint(_lo) + * 2.11. _uhi >= _ulo + * 2.12. _uhi >= juint(_hi) + * + * Proof of lemma 2: + * + * 2.1. _lo <= jint(_ulo): + * According the lemma 1, _ulo is an element of the TypeInt, so in the + * signed domain, it must not be less than the smallest element of that + * TypeInt, which is _lo. Which means that _lo <= _ulo in the signed + * domain, or in a more programmatical way, _lo <= jint(_ulo). + * 2.2. _lo <= _hi: + * According the lemma 1, _hi is an element of the TypeInt, so in the + * signed domain, it must not be less than the smallest element of that + * TypeInt, which is _lo. Which means that _lo <= _hi. + * + * The other inequalities can be proved in a similar manner. + * + * 3. Given 2 jint values x, y where either both >= 0 or both < 0. Then: + * + * x <= y iff juint(x) <= juint(y) + * I.e. x <= y in the signed domain iff x <= y in the unsigned domain + * + * 4. Either _lo == jint(_ulo) and _hi == jint(_uhi), or each element of a + * TypeInt lies in either interval [_lo, jint(_uhi)] or [jint(_ulo), _hi] + * (note that these intervals are disjoint in this case). + * + * Proof of lemma 4: + * + * For a TypeInt t, there are 3 possible cases: + * + * a. t._lo >= 0, we have: + * + * 0 <= t_lo <= jint(t._ulo) (lemma 2.1) + * juint(t._lo) <= juint(jint(t._ulo)) (lemma 3) + * == t._ulo (juint(jint(v)) == v with juint v) + * <= juint(t._lo) (lemma 2.4) + * + * Which means that t._lo == jint(t._ulo). + * + * Furthermore, + * + * 0 <= t._lo <= t._hi (lemma 2.2) + * 0 <= t._lo <= jint(t._uhi) (lemma 2.3) + * t._hi >= jint(t._uhi) (lemma 2.9) + * + * juint(t._hi) >= juint(jint(t._uhi)) (lemma 3) + * == t._uhi (juint(jint(v)) == v with juint v) + * >= juint(t._hi) (lemma 2.12) + * + * Which means that t._hi == jint(t._uhi). + * In this case, t._lo == jint(t._ulo) and t._hi == jint(t._uhi) + * + * b. t._hi < 0. Similarly, we can conclude that: + * t._lo == jint(t._ulo) and t._hi == jint(t._uhi) + * + * c. t._lo < 0, t._hi >= 0. + * + * Since t._ulo <= juint(t._hi) (lemma 2.5), we must have jint(t._ulo) >= 0 + * because all negative values is larger than all non-negative values in the + * unsigned domain. + * + * Since t._uhi >= juint(t._lo) (lemma 2.10), we must have jint(t._uhi) < 0 + * similar to the reasoning above. + * + * In this case, each element of t belongs to either [t._lo, jint(t._uhi)] or + * [jint(t._ulo), t._hi]. + * + * Below is an illustration of the TypeInt in this case, the intervals that + * the elements can be in are marked using the = symbol. Note how the + * negative range in the signed domain wrap around in the unsigned domain. + * + * Signed: + * -----lo=========uhi---------0--------ulo==========hi----- + * Unsigned: + * 0--------ulo==========hi----------lo=========uhi--------- + * + * This property is useful for our analysis of TypeInt values. Additionally, + * it can be seen that _lo and jint(_uhi) are both < 0 or both >= 0, and the + * same applies to jint(_ulo) and _hi. + * + * We call [_lo, jint(_uhi)] and [jint(_ulo), _hi] "simple intervals". Then, + * a TypeInt consists of 2 simple intervals, each of which has its bounds + * being both >= 0 or both < 0. If both simple intervals lie in the same half + * of the integer domain, they must be the same (i.e _lo == jint(_ulo) and + * _hi == jint(_uhi)). Otherwise, [_lo, jint(_uhi)] must lie in the negative + * half and [jint(_ulo), _hi] must lie in the non-negative half of the signed + * domain (equivalently, [_lo, jint(_uhi)] must lie in the upper half and + * [jint(_ulo), _hi] must lie in the lower half of the unsigned domain). + */ +class TypeInt : public TypeInteger { +private: + TypeInt(const TypeIntPrototype& t, int w, bool dual); + static const Type* make_or_top(const TypeIntPrototype& t, int widen, bool dual); + friend class TypeIntHelper; -//------------------------------TypeInt---------------------------------------- -// Class of integer ranges, the set of integers between a lower bound and an -// upper bound, inclusive. -class TypeInt : public TypeInteger { - TypeInt( jint lo, jint hi, int w ); protected: - virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; + virtual const Type* filter_helper(const Type* kills, bool include_speculative) const; public: typedef jint NativeType; - virtual bool eq( const Type *t ) const; + virtual bool eq(const Type* t) const; virtual uint hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton virtual bool empty(void) const; // TRUE if type is vacuous - const jint _lo, _hi; // Lower bound, upper bound + // A value is in the set represented by this TypeInt if it satisfies all + // the below constraints, see contains(jint) + const jint _lo, _hi; // Lower bound, upper bound in the signed domain + const juint _ulo, _uhi; // Lower bound, upper bound in the unsigned domain + const KnownBits _bits; - static const TypeInt *make(jint lo); + static const TypeInt* make(jint con); // must always specify w - static const TypeInt *make(jint lo, jint hi, int w); + static const TypeInt* make(jint lo, jint hi, int widen); + static const Type* make_or_top(const TypeIntPrototype& t, int widen); // Check for single integer - bool is_con() const { return _lo==_hi; } + bool is_con() const { return _lo == _hi; } bool is_con(jint i) const { return is_con() && _lo == i; } - jint get_con() const { assert(is_con(), "" ); return _lo; } + jint get_con() const { assert(is_con(), ""); return _lo; } + // Check if a jint/TypeInt is a subset of this TypeInt (i.e. all elements of the + // argument are also elements of this type) + bool contains(jint i) const; + bool contains(const TypeInt* t) const; - virtual bool is_finite() const; // Has a finite value + virtual bool is_finite() const; // Has a finite value - virtual const Type *xmeet( const Type *t ) const; - virtual const Type *xdual() const; // Compute dual right now. - virtual const Type *widen( const Type *t, const Type* limit_type ) const; - virtual const Type *narrow( const Type *t ) const; + virtual const Type* xmeet(const Type* t) const; + virtual const Type* xdual() const; // Compute dual right now. + virtual const Type* widen(const Type* t, const Type* limit_type) const; + virtual const Type* narrow(const Type* t) const; virtual jlong hi_as_long() const { return _hi; } virtual jlong lo_as_long() const { return _lo; } // Do not kill _widen bits. // Convenience common pre-built types. - static const TypeInt *MAX; - static const TypeInt *MIN; - static const TypeInt *MINUS_1; - static const TypeInt *ZERO; - static const TypeInt *ONE; - static const TypeInt *BOOL; - static const TypeInt *CC; - static const TypeInt *CC_LT; // [-1] == MINUS_1 - static const TypeInt *CC_GT; // [1] == ONE - static const TypeInt *CC_EQ; // [0] == ZERO - static const TypeInt *CC_LE; // [-1,0] - static const TypeInt *CC_GE; // [0,1] == BOOL (!) - static const TypeInt *BYTE; - static const TypeInt *UBYTE; - static const TypeInt *CHAR; - static const TypeInt *SHORT; - static const TypeInt *POS; - static const TypeInt *POS1; - static const TypeInt *INT; - static const TypeInt *SYMINT; // symmetric range [-max_jint..max_jint] - static const TypeInt *TYPE_DOMAIN; // alias for TypeInt::INT - - static const TypeInt *as_self(const Type *t) { return t->is_int(); } + static const TypeInt* MAX; + static const TypeInt* MIN; + static const TypeInt* MINUS_1; + static const TypeInt* ZERO; + static const TypeInt* ONE; + static const TypeInt* BOOL; + static const TypeInt* CC; + static const TypeInt* CC_LT; // [-1] == MINUS_1 + static const TypeInt* CC_GT; // [1] == ONE + static const TypeInt* CC_EQ; // [0] == ZERO + static const TypeInt* CC_NE; // [-1, 1] + static const TypeInt* CC_LE; // [-1,0] + static const TypeInt* CC_GE; // [0,1] == BOOL (!) + static const TypeInt* BYTE; + static const TypeInt* UBYTE; + static const TypeInt* CHAR; + static const TypeInt* SHORT; + static const TypeInt* NON_ZERO; + static const TypeInt* POS; + static const TypeInt* POS1; + static const TypeInt* INT; + static const TypeInt* SYMINT; // symmetric range [-max_jint..max_jint] + static const TypeInt* TYPE_DOMAIN; // alias for TypeInt::INT + + static const TypeInt* as_self(const Type* t) { return t->is_int(); } #ifndef PRODUCT - virtual void dump2( Dict &d, uint depth, outputStream *st ) const; + virtual void dump2(Dict& d, uint depth, outputStream* st) const; + void dump_verbose() const; #endif }; - -//------------------------------TypeLong--------------------------------------- -// Class of long integer ranges, the set of integers between a lower bound and -// an upper bound, inclusive. +// Similar to TypeInt class TypeLong : public TypeInteger { - TypeLong( jlong lo, jlong hi, int w ); +private: + TypeLong(const TypeIntPrototype& t, int w, bool dual); + static const Type* make_or_top(const TypeIntPrototype& t, int widen, bool dual); + + friend class TypeIntHelper; + protected: // Do not kill _widen bits. - virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; + virtual const Type* filter_helper(const Type* kills, bool include_speculative) const; public: typedef jlong NativeType; virtual bool eq( const Type *t ) const; @@ -697,16 +869,25 @@ class TypeLong : public TypeInteger { virtual bool singleton(void) const; // TRUE if type is a singleton virtual bool empty(void) const; // TRUE if type is vacuous public: - const jlong _lo, _hi; // Lower bound, upper bound + // A value is in the set represented by this TypeLong if it satisfies all + // the below constraints, see contains(jlong) + const jlong _lo, _hi; // Lower bound, upper bound in the signed domain + const julong _ulo, _uhi; // Lower bound, upper bound in the unsigned domain + const KnownBits _bits; - static const TypeLong *make(jlong lo); + static const TypeLong* make(jlong con); // must always specify w - static const TypeLong *make(jlong lo, jlong hi, int w); + static const TypeLong* make(jlong lo, jlong hi, int widen); + static const Type* make_or_top(const TypeIntPrototype& t, int widen); // Check for single integer - bool is_con() const { return _lo==_hi; } + bool is_con() const { return _lo == _hi; } bool is_con(jlong i) const { return is_con() && _lo == i; } jlong get_con() const { assert(is_con(), "" ); return _lo; } + // Check if a jlong/TypeLong is a subset of this TypeLong (i.e. all elements of the + // argument are also elements of this type) + bool contains(jlong i) const; + bool contains(const TypeLong* t) const; // Check for positive 32-bit value. int is_positive_int() const { return _lo >= 0 && _hi <= (jlong)max_jint; } @@ -716,27 +897,30 @@ class TypeLong : public TypeInteger { virtual jlong hi_as_long() const { return _hi; } virtual jlong lo_as_long() const { return _lo; } - virtual const Type *xmeet( const Type *t ) const; - virtual const Type *xdual() const; // Compute dual right now. - virtual const Type *widen( const Type *t, const Type* limit_type ) const; - virtual const Type *narrow( const Type *t ) const; + virtual const Type* xmeet(const Type* t) const; + virtual const Type* xdual() const; // Compute dual right now. + virtual const Type* widen(const Type* t, const Type* limit_type) const; + virtual const Type* narrow(const Type* t) const; // Convenience common pre-built types. - static const TypeLong *MAX; - static const TypeLong *MIN; - static const TypeLong *MINUS_1; - static const TypeLong *ZERO; - static const TypeLong *ONE; - static const TypeLong *POS; - static const TypeLong *LONG; - static const TypeLong *INT; // 32-bit subrange [min_jint..max_jint] - static const TypeLong *UINT; // 32-bit unsigned [0..max_juint] - static const TypeLong *TYPE_DOMAIN; // alias for TypeLong::LONG + static const TypeLong* MAX; + static const TypeLong* MIN; + static const TypeLong* MINUS_1; + static const TypeLong* ZERO; + static const TypeLong* ONE; + static const TypeLong* NON_ZERO; + static const TypeLong* POS; + static const TypeLong* NEG; + static const TypeLong* LONG; + static const TypeLong* INT; // 32-bit subrange [min_jint..max_jint] + static const TypeLong* UINT; // 32-bit unsigned [0..max_juint] + static const TypeLong* TYPE_DOMAIN; // alias for TypeLong::LONG // static convenience methods. - static const TypeLong *as_self(const Type *t) { return t->is_long(); } + static const TypeLong* as_self(const Type* t) { return t->is_long(); } #ifndef PRODUCT - virtual void dump2( Dict &d, uint, outputStream *st ) const;// Specialized per-Type dumping + virtual void dump2(Dict& d, uint, outputStream* st) const;// Specialized per-Type dumping + void dump_verbose() const; #endif }; @@ -2246,6 +2430,16 @@ inline const TypeLong* Type::cast() const { return is_long(); } +template <> +inline const TypeInt* Type::try_cast() const { + return isa_int(); +} + +template <> +inline const TypeLong* Type::try_cast() const { + return isa_long(); +} + // =============================================================== // Things that need to be 64-bits in the 64-bit build but // 32-bits in the 32-bit build. Done this way to get full diff --git a/src/hotspot/share/utilities/count_leading_zeros.hpp b/src/hotspot/share/utilities/count_leading_zeros.hpp index d6cbed9a355..122507743d3 100644 --- a/src/hotspot/share/utilities/count_leading_zeros.hpp +++ b/src/hotspot/share/utilities/count_leading_zeros.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #ifndef SHARE_UTILITIES_COUNT_LEADING_ZEROS_HPP #define SHARE_UTILITIES_COUNT_LEADING_ZEROS_HPP +#include "metaprogramming/enableIf.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" @@ -36,7 +37,8 @@ // We implement and support variants for 8, 16, 32 and 64 bit integral types. template struct CountLeadingZerosImpl; -template unsigned count_leading_zeros(T v) { +template ::value)> +unsigned count_leading_zeros(T v) { assert(v != 0, "precondition"); return CountLeadingZerosImpl::doit(v); } diff --git a/src/hotspot/share/utilities/intn_t.hpp b/src/hotspot/share/utilities/intn_t.hpp new file mode 100644 index 00000000000..093db367e17 --- /dev/null +++ b/src/hotspot/share/utilities/intn_t.hpp @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_UTILITIES_INTN_T_HPP +#define SHARE_UTILITIES_INTN_T_HPP + +#include "utilities/count_leading_zeros.hpp" + +#include + +template +class uintn_t; + +// This class represents a signed integer type with the width of exactly nbits +// bits. Conceptually, nbits == 8 gives a type equivalent to int8_t, +// nbits == 16 gives a type equivalent to int16_t, and so on. This class may be +// used to verify the correctness of an algorithm that is supposed to be +// applicable to all fixed-width integral types. With small nbits, it makes it +// possible to perform an exhaustive test that exercises the algorithm with all +// possible input values. +// Implementation-wise, this class currently only supports 0 < nbits <= 8. Also +// note that this class is implemented so that overflows in alrithmetic +// operations are well-defined and wrap-around. +template +class intn_t { + static_assert(0 < nbits && nbits <= 8, "should not be larger than char"); + +private: + // Only the lowest nbits bits are important, operations should act as if it + // sign extends the lowest nbits to an int, performs the calculation on ints, + // then truncates the result to nbits. In practice, we do not need to + // truncate the result, as the lowest nbits will be sign extended in the next + // operations. We can also sign extends the operands sparingly, for example, + // addition or subtraction do not need this sign extension, and we can add or + // subtract the value of _v directly. This is because the lowest nbits bits + // of a sum or a difference only depends on the lowest nbits bits of the + // operands. + uint _v; + + constexpr static uint _mask = (1 << nbits) - 1; + + friend class uintn_t; + +public: + explicit constexpr intn_t(int v) : _v(v) {} + constexpr intn_t() : _v(0) {} + constexpr intn_t(const intn_t&) = default; + constexpr intn_t& operator=(const intn_t&) = default; + explicit constexpr intn_t(uintn_t v); + + // Sign extension + explicit constexpr operator int() const { + int shift = 32 - nbits; + return int(_v << shift) >> shift; + } + + constexpr static int min = std::numeric_limits::max() << (nbits - 1); + constexpr static int max = (1 << (nbits - 1)) - 1; + static_assert(min < max, ""); + + constexpr bool operator==(intn_t o) const { return (_v & _mask) == (o._v & _mask); } + constexpr bool operator<(intn_t o) const { return int(*this) < int(o); } + constexpr bool operator>(intn_t o) const { return int(*this) > int(o); } + constexpr bool operator<=(intn_t o) const { return int(*this) <= int(o); } + constexpr bool operator>=(intn_t o) const { return int(*this) >= int(o); } +}; + +template +unsigned count_leading_zeros(uintn_t); + +// The unsigned version of intn_t +template +class uintn_t { + static_assert(0 < nbits && nbits <= 8, "should not be larger than char"); + +private: + // Similar to intn_t, the difference is that the operation should act + // as if it zero extends the lowest nbits bits of the operands. + uint _v; + + constexpr static uint _mask = (1 << nbits) - 1; + + friend class intn_t; + + friend unsigned count_leading_zeros(uintn_t); + +public: + explicit constexpr uintn_t(int v) : _v(v) {} + constexpr uintn_t() : _v(0) {} + constexpr uintn_t(const uintn_t&) = default; + constexpr uintn_t& operator=(const uintn_t&) = default; + explicit constexpr uintn_t(intn_t v) : _v(v._v) {} + + // Zero extension + explicit constexpr operator uint() const { return _v & _mask; } + + constexpr static int min = 0; + constexpr static int max = _mask; + static_assert(min < max, ""); + + constexpr bool operator==(uintn_t o) const { return (_v & _mask) == (o._v & _mask); } + constexpr bool operator!=(uintn_t o) const { return (_v & _mask) != (o._v & _mask); } + constexpr bool operator<(uintn_t o) const { return (_v & _mask) < (o._v & _mask); } + constexpr bool operator>(uintn_t o) const { return (_v & _mask) > (o._v & _mask); } + constexpr bool operator<=(uintn_t o) const { return (_v & _mask) <= (o._v & _mask); } + constexpr bool operator>=(uintn_t o) const { return (_v & _mask) >= (o._v & _mask); } + constexpr uintn_t operator+(uintn_t o) const { return uintn_t(_v + o._v); } + constexpr uintn_t operator-(uintn_t o) const { return uintn_t(_v - o._v); } + constexpr uintn_t operator&(uintn_t o) const { return uintn_t(_v & o._v); } + constexpr uintn_t operator|(uintn_t o) const { return uintn_t(_v | o._v); } + constexpr uintn_t operator^(uintn_t o) const { return uintn_t(_v ^ o._v); } + constexpr uintn_t operator>>(unsigned int s) const { return uintn_t((_v & _mask) >> s); } + constexpr uintn_t operator<<(unsigned int s) const { return uintn_t(_v << s); } + constexpr uintn_t operator~() const { return uintn_t(~_v); } + constexpr uintn_t operator-() const { return uintn_t(-_v); } + constexpr uintn_t& operator|=(uintn_t o) { _v |= o._v; return *this; } +}; + +template +constexpr intn_t::intn_t(uintn_t v) : _v(v._v) {} + +namespace std { + +template +class numeric_limits> { +public: + constexpr static intn_t min() { return intn_t(intn_t::min); } + constexpr static intn_t max() { return intn_t(intn_t::max); } +}; + +template +class numeric_limits> { +public: + constexpr static uintn_t min() { return uintn_t(uintn_t::min); } + constexpr static uintn_t max() { return uintn_t(uintn_t::max); } +}; + +} // namespace std + +template +inline unsigned count_leading_zeros(uintn_t v) { + return count_leading_zeros(v._v & uintn_t::_mask) - (32 - nbits); +} + +#endif // SHARE_UTILITIES_INTN_T_HPP diff --git a/test/hotspot/gtest/opto/test_rangeinference.cpp b/test/hotspot/gtest/opto/test_rangeinference.cpp new file mode 100644 index 00000000000..1a62941a486 --- /dev/null +++ b/test/hotspot/gtest/opto/test_rangeinference.cpp @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "opto/rangeinference.hpp" +#include "opto/type.hpp" +#include "runtime/os.hpp" +#include "utilities/intn_t.hpp" +#include "unittest.hpp" + +template +static U uniform_random(); + +template <> +juint uniform_random() { + return os::random(); +} + +template <> +julong uniform_random() { + return (julong(os::random()) << 32) | julong(juint(os::random())); +} + +static void test_canonicalize_constraints_trivial() { + ASSERT_FALSE(TypeInt::NON_ZERO->contains(0)); + ASSERT_TRUE(TypeInt::NON_ZERO->contains(1)); + ASSERT_TRUE(TypeInt::NON_ZERO->contains(-1)); + ASSERT_TRUE(TypeInt::CC_NE->contains(-1)); + ASSERT_TRUE(TypeInt::CC_NE->contains(1)); + ASSERT_FALSE(TypeInt::CC_NE->contains(0)); + ASSERT_FALSE(TypeInt::CC_NE->contains(-2)); + ASSERT_FALSE(TypeInt::CC_NE->contains(2)); + ASSERT_FALSE(TypeLong::NON_ZERO->contains(jlong(0))); + ASSERT_TRUE(TypeLong::NON_ZERO->contains(jlong(1))); + ASSERT_TRUE(TypeLong::NON_ZERO->contains(jlong(-1))); +} + +template +static void test_canonicalize_constraints_exhaustive() { + { + TypeIntPrototype t{{S(0), S(0)}, {U(0), U(0)}, {U(-1), U(0)}}; + auto new_t = t.canonicalize_constraints(); + ASSERT_TRUE(new_t._present); + DEBUG_ONLY(ASSERT_TRUE(t.contains(S(0)))); + DEBUG_ONLY(ASSERT_FALSE(t.contains(S(1)))); + } + { + TypeIntPrototype t{{S(0), S(0)}, {U(1), U(1)}, {U(-1), U(0)}}; + auto new_t = t.canonicalize_constraints(); + ASSERT_FALSE(new_t._present); + DEBUG_ONLY(ASSERT_FALSE(t.contains(S(0)))); + DEBUG_ONLY(ASSERT_FALSE(t.contains(S(1)))); + } + { + TypeIntPrototype t{{S(S::min), S(S::max)}, {U(U::min), U(U::max)}, {U(0), U(0)}}; + auto new_t = t.canonicalize_constraints(); + ASSERT_TRUE(new_t._present); + for (int v = S::min; v <= S::max; v++) { + DEBUG_ONLY(ASSERT_TRUE(t.contains(S(v)))); + } + } + for (int lo = S::min; lo <= S::max; lo++) { + for (int hi = lo; hi <= S::max; hi++) { + for (int ulo = U::min; ulo <= U::max; ulo++) { + for (int uhi = ulo; uhi <= U::max; uhi++) { + for (int zeros = U::min; zeros <= U::max; zeros++) { + for (int ones = U::min; ones <= U::max; ones++) { + TypeIntPrototype t{{S(lo), S(hi)}, {U(ulo), U(uhi)}, {U(zeros), U(ones)}}; + auto new_t = t.canonicalize_constraints(); + if (new_t._present) { + DEBUG_ONLY(new_t._data.verify_constraints()); + } + for (int v = S::min; v <= S::max; v++) { + if (!new_t._present) { + DEBUG_ONLY(ASSERT_FALSE(t.contains(S(v)))); + } else { + DEBUG_ONLY(ASSERT_EQ(t.contains(S(v)), new_t._data.contains(S(v)))); + } + } + } + } + } + } + } + } +} + +template +static void test_canonicalize_constraints_simple() { + constexpr int parameters = 1000; + for (int i = 0; i < parameters; i++) { + S a = uniform_random(); + S b = uniform_random(); + + { + S lo = MIN2(a, b); + S hi = MAX2(a, b); + TypeIntPrototype t{{lo, hi}, {std::numeric_limits::min(), std::numeric_limits::max()}, + {0, 0}}; + auto new_t = t.canonicalize_constraints(); + ASSERT_TRUE(new_t._present); + DEBUG_ONLY(new_t._data.verify_constraints()); + ASSERT_EQ(lo, new_t._data._srange._lo); + ASSERT_EQ(hi, new_t._data._srange._hi); + if (U(lo) <= U(hi)) { + ASSERT_EQ(U(lo), new_t._data._urange._lo); + ASSERT_EQ(U(hi), new_t._data._urange._hi); + } else { + ASSERT_EQ(std::numeric_limits::min(), new_t._data._urange._lo); + ASSERT_EQ(std::numeric_limits::max(), new_t._data._urange._hi); + } + } + + { + U ulo = MIN2(a, b); + U uhi = MAX2(a, b); + TypeIntPrototype t{{std::numeric_limits::min(), std::numeric_limits::max()}, + {ulo, uhi}, {0, 0}}; + auto new_t = t.canonicalize_constraints(); + ASSERT_TRUE(new_t._present); + DEBUG_ONLY(new_t._data.verify_constraints()); + ASSERT_EQ(ulo, new_t._data._urange._lo); + ASSERT_EQ(uhi, new_t._data._urange._hi); + if (S(ulo) <= S(uhi)) { + ASSERT_EQ(S(ulo), new_t._data._srange._lo); + ASSERT_EQ(S(uhi), new_t._data._srange._hi); + } else { + ASSERT_EQ(std::numeric_limits::min(), new_t._data._srange._lo); + ASSERT_EQ(std::numeric_limits::max(), new_t._data._srange._hi); + } + } + + { + U intersection = a & b; + U zeros = a ^ intersection; + U ones = b ^ intersection; + TypeIntPrototype t{{std::numeric_limits::min(), std::numeric_limits::max()}, + {std::numeric_limits::min(), std::numeric_limits::max()}, {zeros, ones}}; + auto new_t = t.canonicalize_constraints(); + ASSERT_TRUE(new_t._present); + DEBUG_ONLY(new_t._data.verify_constraints()); + ASSERT_EQ(zeros, new_t._data._bits._zeros); + ASSERT_EQ(ones, new_t._data._bits._ones); + ASSERT_EQ(ones, new_t._data._urange._lo); + ASSERT_EQ(~zeros, new_t._data._urange._hi); + } + } +} + +template +static void test_canonicalize_constraints_random() { + constexpr int samples = 1000; + constexpr int parameters = 1000; + for (int i = 0; i < parameters; i++) { + S s1 = uniform_random(); + S s2 = uniform_random(); + S lo = MIN2(s1, s2); + S hi = MAX2(s1, s2); + U u1 = uniform_random(); + U u2 = uniform_random(); + U ulo = MIN2(u1, u2); + U uhi = MAX2(u1, u2); + U b1 = uniform_random(); + U b2 = uniform_random(); + U intersection = b1 & b2; + U zeros = b1 ^ intersection; + U ones = b2 ^ intersection; + TypeIntPrototype t{{lo, hi}, {ulo, uhi}, {zeros, ones}}; + auto new_t = t.canonicalize_constraints(); + if (new_t._present) { + DEBUG_ONLY(new_t._data.verify_constraints()); + } + for (int j = 0; j < samples; j++) { + S v = uniform_random(); + if (!new_t._present) { + DEBUG_ONLY(ASSERT_FALSE(t.contains(v))); + } else { + DEBUG_ONLY(ASSERT_EQ(t.contains(v), new_t._data.contains(v))); + } + } + } +} + +TEST_VM(opto, canonicalize_constraints) { + test_canonicalize_constraints_trivial(); + test_canonicalize_constraints_exhaustive, uintn_t<1>>(); + test_canonicalize_constraints_exhaustive, uintn_t<2>>(); + test_canonicalize_constraints_exhaustive, uintn_t<3>>(); + test_canonicalize_constraints_exhaustive, uintn_t<4>>(); + test_canonicalize_constraints_simple(); + test_canonicalize_constraints_simple(); + test_canonicalize_constraints_random(); + test_canonicalize_constraints_random(); +} diff --git a/test/hotspot/gtest/utilities/test_intn_t.cpp b/test/hotspot/gtest/utilities/test_intn_t.cpp new file mode 100644 index 00000000000..89958e0757e --- /dev/null +++ b/test/hotspot/gtest/utilities/test_intn_t.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "utilities/intn_t.hpp" +#include "unittest.hpp" + +// Sanity tests for off-by-one errors +static_assert(intn_t<1>::min == -1 && intn_t<1>::max == 0, ""); +static_assert(intn_t<2>::min == -2 && intn_t<2>::max == 1, ""); +static_assert(intn_t<3>::min == -4 && intn_t<3>::max == 3, ""); +static_assert(uintn_t<1>::max == 1, ""); +static_assert(uintn_t<2>::max == 3, ""); +static_assert(uintn_t<3>::max == 7, ""); + +template +static void test_intn_t() { + static_assert(std::numeric_limits>::min() <= intn_t(-1) && + intn_t(-1) < intn_t(0) && + intn_t(0) <= std::numeric_limits>::max(), "basic sanity"); + constexpr int period = intn_t::max - intn_t::min + 1; + for (int i = std::numeric_limits::min(); i < std::numeric_limits::max(); i++) { + ASSERT_EQ(intn_t(i), intn_t(i + period)); + ASSERT_EQ(int(intn_t(i)), int(intn_t(i + period))); + } + for (int i = intn_t::min; i <= intn_t::max; i++) { + ASSERT_EQ(i, int(intn_t(i))); + if (i > intn_t::min) { + ASSERT_TRUE(intn_t(i - 1) < intn_t(i)); + } else { + ASSERT_TRUE(intn_t(i - 1) > intn_t(i)); + } + if (i < intn_t::max) { + ASSERT_TRUE(intn_t(i) < intn_t(i + 1)); + } else { + ASSERT_TRUE(intn_t(i) > intn_t(i + 1)); + } + } +} + +TEST(utilities, intn_t) { + test_intn_t<1>(); + test_intn_t<2>(); + test_intn_t<3>(); + test_intn_t<4>(); + test_intn_t<5>(); + test_intn_t<6>(); + test_intn_t<7>(); + test_intn_t<8>(); +} From 9aeacf2de5bb8758dd614da365262338b0d26d6f Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Fri, 13 Jun 2025 06:33:42 +0000 Subject: [PATCH 038/213] 8358958: (aio) AsynchronousByteChannel.read/write should throw IAE if buffer is thread-confined Reviewed-by: jpai, bpb --- .../java/lang/foreign/MemorySegment.java | 4 +- .../nio/channels/AsynchronousByteChannel.java | 16 +- .../nio/channels/AsynchronousFileChannel.java | 20 +- .../channels/AsynchronousSocketChannel.java | 18 +- .../nio/ch/AsynchronousFileChannelImpl.java | 18 +- .../nio/ch/AsynchronousSocketChannelImpl.java | 29 +- .../share/classes/sun/nio/ch/IOUtil.java | 2 +- .../channels/TestAsyncSocketChannels.java | 12 +- .../java/nio/channels/etc/MemorySegments.java | 351 +++++++++++++++++- 9 files changed, 437 insertions(+), 33 deletions(-) diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index 3d85e4c32cc..196f44d1abe 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -1120,9 +1120,7 @@ MemorySegment reinterpret(long newSize, *

* If this segment is {@linkplain #isAccessibleBy(Thread) accessible} from a single * thread, calling read/write I/O operations on the resulting buffer might result in - * unspecified exceptions being thrown. Examples of such problematic operations are - * {@link java.nio.channels.AsynchronousSocketChannel#read(ByteBuffer)} and - * {@link java.nio.channels.AsynchronousSocketChannel#write(ByteBuffer)}. + * unspecified exceptions being thrown. *

* Finally, the resulting buffer's byte order is * {@link java.nio.ByteOrder#BIG_ENDIAN}; this can be changed using diff --git a/src/java.base/share/classes/java/nio/channels/AsynchronousByteChannel.java b/src/java.base/share/classes/java/nio/channels/AsynchronousByteChannel.java index 56003d53ec7..c65e836c99a 100644 --- a/src/java.base/share/classes/java/nio/channels/AsynchronousByteChannel.java +++ b/src/java.base/share/classes/java/nio/channels/AsynchronousByteChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.nio.channels; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; import java.nio.ByteBuffer; import java.util.concurrent.Future; @@ -97,7 +99,8 @@ public interface AsynchronousByteChannel * The completion handler * * @throws IllegalArgumentException - * If the buffer is read-only + * If the buffer is read-only or a view of a {@link MemorySegment} + * allocated from a {@linkplain Arena#ofConfined() thread-confined arena} * @throws ReadPendingException * If the channel does not allow more than one read to be outstanding * and a previous read has not completed @@ -128,7 +131,8 @@ void read(ByteBuffer dst, * @return A Future representing the result of the operation * * @throws IllegalArgumentException - * If the buffer is read-only + * If the buffer is read-only or a view of a {@link MemorySegment} + * allocated from a {@linkplain Arena#ofConfined() thread-confined arena} * @throws ReadPendingException * If the channel does not allow more than one read to be outstanding * and a previous read has not completed @@ -177,6 +181,9 @@ void read(ByteBuffer dst, * @param handler * The completion handler object * + * @throws IllegalArgumentException + * If the buffer is a view of a {@link MemorySegment} allocated from a + * {@linkplain Arena#ofConfined() thread-confined arena} * @throws WritePendingException * If the channel does not allow more than one write to be outstanding * and a previous write has not completed @@ -205,6 +212,9 @@ void write(ByteBuffer src, * * @return A Future representing the result of the operation * + * @throws IllegalArgumentException + * If the buffer is a view of a {@link MemorySegment} allocated from a + * {@linkplain Arena#ofConfined() thread-confined arena} * @throws WritePendingException * If the channel does not allow more than one write to be outstanding * and a previous write has not completed diff --git a/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java b/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java index 15af714accf..265ad80a443 100644 --- a/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java +++ b/src/java.base/share/classes/java/nio/channels/AsynchronousFileChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.nio.channels; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; import java.nio.file.*; import java.nio.file.attribute.FileAttribute; import java.nio.file.spi.*; @@ -693,7 +695,9 @@ public final FileLock tryLock() throws IOException { * The handler for consuming the result * * @throws IllegalArgumentException - * If the position is negative or the buffer is read-only + * If the position is negative, or the buffer is read-only or a view of a + * {@link MemorySegment} allocated from a {@linkplain Arena#ofConfined() + * thread-confined arena} * @throws NonReadableChannelException * If this channel was not opened for reading */ @@ -728,7 +732,9 @@ public abstract void read(ByteBuffer dst, * @return A {@code Future} object representing the pending result * * @throws IllegalArgumentException - * If the position is negative or the buffer is read-only + * If the position is negative, or the buffer is read-only or a view of a + * {@link MemorySegment} allocated from a {@linkplain Arena#ofConfined() + * thread-confined arena} * @throws NonReadableChannelException * If this channel was not opened for reading */ @@ -759,7 +765,9 @@ public abstract void read(ByteBuffer dst, * The handler for consuming the result * * @throws IllegalArgumentException - * If the position is negative + * If the position is negative or the buffer is a view of a {@link + * MemorySegment} allocated from a {@linkplain Arena#ofConfined() + * thread-confined arena} * @throws NonWritableChannelException * If this channel was not opened for writing */ @@ -795,7 +803,9 @@ public abstract void write(ByteBuffer src, * @return A {@code Future} object representing the pending result * * @throws IllegalArgumentException - * If the position is negative + * If the position is negative or the buffer is a view of a {@link + * MemorySegment} allocated from a {@linkplain Arena#ofConfined() + * thread-confined arena} * @throws NonWritableChannelException * If this channel was not opened for writing */ diff --git a/src/java.base/share/classes/java/nio/channels/AsynchronousSocketChannel.java b/src/java.base/share/classes/java/nio/channels/AsynchronousSocketChannel.java index 736327a1825..5c65048e091 100644 --- a/src/java.base/share/classes/java/nio/channels/AsynchronousSocketChannel.java +++ b/src/java.base/share/classes/java/nio/channels/AsynchronousSocketChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.nio.channels; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; import java.nio.channels.spi.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.Future; @@ -379,7 +381,8 @@ public abstract void connect(SocketAddress remote, * The handler for consuming the result * * @throws IllegalArgumentException - * If the buffer is read-only + * If the buffer is read-only or a view of a {@link MemorySegment} + * allocated from a {@linkplain Arena#ofConfined() thread-confined arena} * @throws ReadPendingException * If a read operation is already in progress on this channel * @throws NotYetConnectedException @@ -488,7 +491,8 @@ public final void read(ByteBuffer dst, * If the pre-conditions for the {@code offset} and {@code length} * parameter aren't met * @throws IllegalArgumentException - * If the buffer is read-only + * If any of the buffers is read-only or a view of a {@link MemorySegment} + * allocated from a {@linkplain Arena#ofConfined() thread-confined arena} * @throws ReadPendingException * If a read operation is already in progress on this channel * @throws NotYetConnectedException @@ -538,6 +542,9 @@ public abstract void read(ByteBuffer[] dsts, * @param handler * The handler for consuming the result * + * @throws IllegalArgumentException + * If the buffer is a view of a {@link MemorySegment} allocated from + * a {@linkplain Arena#ofConfined() thread-confined arena} * @throws WritePendingException * If a write operation is already in progress on this channel * @throws NotYetConnectedException @@ -552,6 +559,7 @@ public abstract void write(ByteBuffer src, CompletionHandler handler); /** + * @throws IllegalArgumentException {@inheritDoc} * @throws WritePendingException {@inheritDoc} * @throws NotYetConnectedException * If this channel is not yet connected @@ -568,6 +576,7 @@ public final void write(ByteBuffer src, } /** + * @throws IllegalArgumentException {@inheritDoc} * @throws WritePendingException {@inheritDoc} * @throws NotYetConnectedException * If this channel is not yet connected @@ -638,6 +647,9 @@ public final void write(ByteBuffer src, * @param handler * The handler for consuming the result * + * @throws IllegalArgumentException + * If any of the buffers is a view of a {@link MemorySegment} + * allocated from a {@linkplain Arena#ofConfined() thread-confined arena} * @throws IndexOutOfBoundsException * If the pre-conditions for the {@code offset} and {@code length} * parameter aren't met diff --git a/src/java.base/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java index 2ca1f8a87b8..28d067ebc74 100644 --- a/src/java.base/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousFileChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import java.util.concurrent.locks.*; import java.io.FileDescriptor; import java.io.IOException; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; /** * Base implementation of AsynchronousFileChannel. @@ -40,6 +42,8 @@ abstract class AsynchronousFileChannelImpl extends AsynchronousFileChannel { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // close support protected final ReadWriteLock closeLock = new ReentrantReadWriteLock(); protected volatile boolean closed; @@ -215,6 +219,10 @@ abstract Future implRead(ByteBuffer dst, @Override public final Future read(ByteBuffer dst, long position) { + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + if (NIO_ACCESS.isThreadConfined(dst)) + throw new IllegalArgumentException("Buffer is thread confined"); return implRead(dst, position, null, null); } @@ -226,6 +234,10 @@ public final void read(ByteBuffer dst, { if (handler == null) throw new NullPointerException("'handler' is null"); + if (dst.isReadOnly()) + throw new IllegalArgumentException("Read-only buffer"); + if (NIO_ACCESS.isThreadConfined(dst)) + throw new IllegalArgumentException("Buffer is thread confined"); implRead(dst, position, attachment, handler); } @@ -237,6 +249,8 @@ abstract Future implWrite(ByteBuffer src, @Override public final Future write(ByteBuffer src, long position) { + if (NIO_ACCESS.isThreadConfined(src)) + throw new IllegalArgumentException("Buffer is thread confined"); return implWrite(src, position, null, null); } @@ -248,6 +262,8 @@ public final void write(ByteBuffer src, { if (handler == null) throw new NullPointerException("'handler' is null"); + if (NIO_ACCESS.isThreadConfined(src)) + throw new IllegalArgumentException("Buffer is thread confined"); implWrite(src, position, attachment, handler); } } diff --git a/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index c53aca8b1c7..68983304735 100644 --- a/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,8 @@ import java.util.Collections; import java.util.concurrent.*; import java.util.concurrent.locks.*; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.net.NetHooks; import sun.net.ext.ExtendedSocketOptions; @@ -50,6 +52,8 @@ abstract class AsynchronousSocketChannelImpl extends AsynchronousSocketChannel implements Cancellable, Groupable { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + protected final FileDescriptor fd; // protects state, localAddress, and remoteAddress @@ -281,6 +285,8 @@ private Future read(boolean isScatteringRead, public final Future read(ByteBuffer dst) { if (dst.isReadOnly()) throw new IllegalArgumentException("Read-only buffer"); + if (NIO_ACCESS.isThreadConfined(dst)) + throw new IllegalArgumentException("Buffer is thread confined"); return read(false, dst, null, 0L, TimeUnit.MILLISECONDS, null, null); } @@ -295,6 +301,8 @@ public final void read(ByteBuffer dst, throw new NullPointerException("'handler' is null"); if (dst.isReadOnly()) throw new IllegalArgumentException("Read-only buffer"); + if (NIO_ACCESS.isThreadConfined(dst)) + throw new IllegalArgumentException("Buffer is thread confined"); read(false, dst, null, timeout, unit, attachment, handler); } @@ -310,12 +318,14 @@ public final void read(ByteBuffer[] dsts, if (handler == null) throw new NullPointerException("'handler' is null"); Objects.checkFromIndexSize(offset, length, dsts.length); - ByteBuffer[] bufs = Util.subsequence(dsts, offset, length); - for (int i=0; i Future write(boolean isGatheringWrite, @Override public final Future write(ByteBuffer src) { + if (NIO_ACCESS.isThreadConfined(src)) + throw new IllegalArgumentException("Buffer is thread confined"); return write(false, src, null, 0L, TimeUnit.MILLISECONDS, null, null); } @@ -396,6 +408,8 @@ public final void write(ByteBuffer src, { if (handler == null) throw new NullPointerException("'handler' is null"); + if (NIO_ACCESS.isThreadConfined(src)) + throw new IllegalArgumentException("Buffer is thread confined"); write(false, src, null, timeout, unit, attachment, handler); } @@ -412,6 +426,11 @@ public final void write(ByteBuffer[] srcs, throw new NullPointerException("'handler' is null"); Objects.checkFromIndexSize(offset, length, srcs.length); srcs = Util.subsequence(srcs, offset, length); + for (ByteBuffer src : srcs) { + if (NIO_ACCESS.isThreadConfined(src)) { + throw new IllegalArgumentException("Buffer is thread confined"); + } + } write(true, null, srcs, timeout, unit, attachment, handler); } diff --git a/src/java.base/share/classes/sun/nio/ch/IOUtil.java b/src/java.base/share/classes/sun/nio/ch/IOUtil.java index ad1aedc2668..45f8cb2e588 100644 --- a/src/java.base/share/classes/sun/nio/ch/IOUtil.java +++ b/src/java.base/share/classes/sun/nio/ch/IOUtil.java @@ -479,7 +479,7 @@ static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, static void acquireScope(ByteBuffer bb, boolean async) { if (async && NIO_ACCESS.isThreadConfined(bb)) { - throw new IllegalStateException("Confined session not supported"); + throw new IllegalArgumentException("Buffer is thread confined"); } NIO_ACCESS.acquireSession(bb); } diff --git a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java index 35d938ec1d3..37fef8bb4b6 100644 --- a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,7 @@ public class TestAsyncSocketChannels extends AbstractChannelsTest { static final Class IOE = IOException.class; static final Class EE = ExecutionException.class; + static final Class IAE = IllegalArgumentException.class; static final Class ISE = IllegalStateException.class; /** Tests that confined sessions are not supported. */ @@ -79,8 +80,8 @@ public void testWithConfined(Supplier arenaSupplier) var bb = segment.asByteBuffer(); var bba = new ByteBuffer[] { bb }; List> ioOps = List.of( - handler -> handler.propagateHandlerFromFuture(channel.write(bb)), - handler -> handler.propagateHandlerFromFuture(channel.read(bb)), + handler -> channel.write(bb), + handler -> channel.read(bb), handler -> channel.write(bb, null, handler), handler -> channel.read( bb, null, handler), handler -> channel.write(bb , 0L, SECONDS, null, handler), @@ -91,10 +92,7 @@ public void testWithConfined(Supplier arenaSupplier) for (var ioOp : ioOps) { out.println("testAsyncWithConfined - op"); var handler = new TestHandler(); - ioOp.accept(handler); - handler.await() - .assertFailedWith(ISE) - .assertExceptionMessage("Confined session not supported"); + expectThrows(IAE, () -> ioOp.accept(handler)); } } } diff --git a/test/jdk/java/nio/channels/etc/MemorySegments.java b/test/jdk/java/nio/channels/etc/MemorySegments.java index 77da11759c7..2d82d855fa2 100644 --- a/test/jdk/java/nio/channels/etc/MemorySegments.java +++ b/test/jdk/java/nio/channels/etc/MemorySegments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,9 +23,9 @@ /* * @test - * @bug 8333849 - * @summary Test ByteChannel implementations of read and write with ByteBuffers that are - * backed by MemorySegments allocated from an Arena + * @bug 8333849 8358958 + * @summary Test ByteChannel and AsycnhronousByteChannel implementations with ByteBuffers + * that are views of a MemorySegment * @run junit MemorySegments */ @@ -35,6 +35,10 @@ import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.ByteBuffer; +import java.nio.channels.AsynchronousFileChannel; +import java.nio.channels.AsynchronousServerSocketChannel; +import java.nio.channels.AsynchronousSocketChannel; +import java.nio.channels.CompletionHandler; import java.nio.channels.DatagramChannel; import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; @@ -42,10 +46,18 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Random; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import java.util.stream.Stream; import static java.nio.file.StandardOpenOption.*; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.RepeatedTest; +import org.junit.jupiter.api.condition.DisabledOnOs; +import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import static org.junit.jupiter.api.Assertions.*; @@ -325,6 +337,177 @@ void testDatagramChannelScatteringRead(Supplier arenaSupplier) throws IOE } } + /** + * AsynchronousSocketChannel read/write(ByteBuffer). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testAsyncSocketChannelReadWrite(Supplier arenaSupplier) throws Exception { + boolean shared = isShared(arenaSupplier); + boolean confined = isConfined(arenaSupplier); + Arena arena = arenaSupplier.get(); + + try (var listener = AsynchronousServerSocketChannel.open(); + AsynchronousSocketChannel ch1 = AsynchronousSocketChannel.open()) { + listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + + ch1.connect(listener.getLocalAddress()).get(); + try (AsynchronousSocketChannel ch2 = listener.accept().get()) { + ByteBuffer dst = arena.allocate(SIZE + 100).asByteBuffer(); + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + + if (confined) { + // read and write should fail with IAE + assertThrows(IllegalArgumentException.class, () -> ch1.read(dst)); + assertThrows(IllegalArgumentException.class, () -> ch2.write(src)); + } else { + // async read + Future readTask = ch1.read(dst); + + // shared arena cannot be closed while read in progress + if (shared) { + assertThrows(IllegalStateException.class, arena::close); + } + + // async write + Future writeTask = ch2.write(src); + + // finish write + int nwritten = writeTask.get(); + assertTrue(nwritten > 0); + assertTrue(nwritten <= SIZE); + assertEquals(nwritten, src.position()); + + // finish read + int nread = readTask.get(); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertEquals(nread, dst.position()); + + // check contents + dst.flip(); + assertEquals(src.slice(0, nread), dst); + } + } + } finally { + tryClose(arena); + } + } + + /** + * AsynchronousSocketChannel write(ByteBuffer[]). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testAsyncSocketChannelGatheringWrite(Supplier arenaSupplier) throws Throwable { + boolean confined = isConfined(arenaSupplier); + Arena arena = arenaSupplier.get(); + + try (var listener = AsynchronousServerSocketChannel.open(); + AsynchronousSocketChannel ch1 = AsynchronousSocketChannel.open()) { + listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + + ch1.connect(listener.getLocalAddress()).get(); + try (AsynchronousSocketChannel ch2 = listener.accept().get()) { + + ByteBuffer src = arena.allocate(SIZE * 2).asByteBuffer(); + fillRandom(src); + ByteBuffer src1 = src.slice(0, SIZE); + ByteBuffer src2 = src.slice(SIZE, SIZE); + var srcs = new ByteBuffer[] { src1, src2 }; + + var writeHandler = new Handler(); + if (confined) { + assertThrows(IllegalArgumentException.class, + () -> ch1.write(srcs, 0, 2, 0, TimeUnit.SECONDS, null, writeHandler)); + } else { + // async gathering write + ch1.write(srcs, 0, 2, 0, TimeUnit.SECONDS, null, writeHandler); + + // finish gathering write + int nwritten = (int) (long) writeHandler.join(); + assertTrue(nwritten > 0); + assertEquals(Math.min(nwritten, SIZE), src1.position()); + assertEquals(nwritten, src1.position() + src2.position()); + + // async read + finish read + ByteBuffer dst = arena.allocate(SIZE * 2 + 50).asByteBuffer(); + int nread = ch2.read(dst).get(); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertEquals(nread, dst.position()); + + // check contents + dst.flip(); + assertEquals(src.slice(0, nread), dst); + } + } + } finally { + tryClose(arena); + } + } + + /** + * AsynchronousSocketChannel read(ByteBuffer[]). + */ + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testAsyncSocketChannelScatteringRead(Supplier arenaSupplier) throws Throwable { + boolean shared = isShared(arenaSupplier); + boolean confined = isConfined(arenaSupplier); + Arena arena = arenaSupplier.get(); + + try (var listener = AsynchronousServerSocketChannel.open(); + AsynchronousSocketChannel ch1 = AsynchronousSocketChannel.open()) { + listener.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + + ch1.connect(listener.getLocalAddress()).get(); + try (AsynchronousSocketChannel ch2 = listener.accept().get()) { + + ByteBuffer dst = arena.allocate(SIZE + 50).asByteBuffer(); + ByteBuffer dst1 = dst.slice(0, 50); + ByteBuffer dst2 = dst.slice(50, dst.capacity() - 50); + var dsts = new ByteBuffer[]{dst1, dst2}; + var readHandler = new Handler(); + + if (confined) { + assertThrows(IllegalArgumentException.class, + () -> ch1.read(dsts, 0, 2, 0, TimeUnit.SECONDS, null, readHandler)); + } else { + // async scattering read + ch1.read(dsts, 0, 2, 0, TimeUnit.SECONDS, null, readHandler); + + // shared arena cannot be closed while read in progress + if (shared) { + assertThrows(IllegalStateException.class, arena::close); + } + + // async write + finish write + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + int nwritten = ch2.write(src).get(); + assertTrue(nwritten > 0); + assertTrue(nwritten <= SIZE); + assertEquals(nwritten, src.position()); + + // finish scattering read + int nread = (int) (long) readHandler.join(); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertTrue(dst1.position() > 0); + assertEquals(nread, dst1.position() + dst2.position()); + + // check contents + src.flip(); + assertEquals(src, dst.slice(0, nread)); + } + } + } finally { + tryClose(arena); + } + } + /** * FileChannel read/write(ByteBuffer). */ @@ -467,6 +650,129 @@ void testFileChannelScatteringRead(Supplier arenaSupplier) throws IOExcep } } + /** + * AsynchronousFileChannel read/write(ByteBuffer). + */ + @DisabledOnOs(OS.WINDOWS) + @ParameterizedTest + @MethodSource("arenaSuppliers") + void testAsyncFileChannelReadWrite(Supplier arenaSupplier) throws Throwable { + boolean confined = isConfined(arenaSupplier); + Arena arena = arenaSupplier.get(); + + Path file = Files.createTempFile(Path.of(""), "foo", ".dat"); + try (AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, READ, WRITE)) { + ByteBuffer dst = arena.allocate(SIZE + 100).asByteBuffer(); + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + + if (confined) { + // read and write should fail with IAE + assertThrows(IllegalArgumentException.class, () -> ch.read(dst, 0L)); + assertThrows(IllegalArgumentException.class, () -> ch.write(src, 0L)); + } else { + // async write + Future writeTask = ch.write(src, 0L); + + // finish write + int nwritten = writeTask.get(); + assertTrue(nwritten > 0); + assertTrue(nwritten <= SIZE); + assertEquals(nwritten, src.position()); + + // async read + Future readTask = ch.read(dst, 0L); + + // finish read + int nread = readTask.get(); + assertTrue(nread > 0); + assertTrue(nread <= nwritten); + assertEquals(nread, dst.position()); + + // check contents + dst.flip(); + assertEquals(src.slice(0, nread), dst); + } + } finally { + tryClose(arena); + } + } + + /** + * Test closing a shared arena while AsynchronousFileChannel.write in progress. + */ + @Disabled + @RepeatedTest(20) + void testAsyncFileChannelWriteRacingArenaClose() throws Exception { + Path file = Files.createTempFile(Path.of(""), "foo", ".dat"); + + // use SYNC option to cause write operation to be slow + try (AsynchronousFileChannel ch = AsynchronousFileChannel.open(file, READ, WRITE, SYNC)) { + Arena arena = Arena.ofShared(); + boolean closed = false; + try { + ByteBuffer src = arena.allocate(SIZE).asByteBuffer(); + fillRandom(src); + + // need copy of source buffer so that writing can be tested after arena is closed + ByteBuffer srcCopy = copyOf(src); + + // async write + Future writeTask = ch.write(src, 0L); + + // attempt to close arena, races with write operation + try { + arena.close(); + closed = true; + } catch (IllegalStateException e) { + // in use + } + + // finish write + int nwritten = writeTask.get(); + assertTrue(nwritten > 0); + assertTrue(nwritten <= SIZE); + + // read and check contents + ByteBuffer dst = ByteBuffer.allocate(SIZE + 100); + int nread = ch.read(dst, 0L).get(); + dst.flip(); + assertEquals(srcCopy.slice(0, nread), dst); + } finally { + if (!closed) { + arena.close(); + } + } + } + } + + /** + * CompletionHandler with a join method to wait for operation to complete. + */ + private static class Handler implements CompletionHandler { + volatile V result; + volatile Throwable ex; + final CountDownLatch latch = new CountDownLatch(1); + @Override + public void completed(V result, Void att) { + this.result = result; + latch.countDown(); + } + @Override + public void failed(Throwable ex, Void att) { + this.ex = ex; + latch.countDown(); + } + V join() throws ExecutionException, InterruptedException { + latch.await(); + Throwable ex = this.ex; + if (ex != null) { + throw new ExecutionException(ex); + } + return result; + } + } + /** * Fill the buffer with random bytes. */ @@ -479,6 +785,42 @@ private void fillRandom(ByteBuffer bb) { bb.position(pos); } + /** + * Return a copy of a buffer. + */ + private ByteBuffer copyOf(ByteBuffer buf) { + ByteBuffer copy = ByteBuffer.allocate(buf.capacity()); + buf.put(copy); + buf.flip(); + copy.flip(); + assertEquals(buf, copy); + return copy; + } + + /** + * Returns true if the supplier produces shared arenas. + */ + private boolean isShared(Supplier arenaSupplier) { + if (!isConfined(arenaSupplier)) { + try { + arenaSupplier.get().close(); + return true; + } catch (UnsupportedOperationException e) { } + } + // confined or non-closeable + return false; + } + + /** + * Returns true if the supplier produces thread-confined arenas. + */ + private boolean isConfined(Supplier arenaSupplier) { + Arena arena = arenaSupplier.get(); + boolean confined = !arena.allocate(0).isAccessibleBy(new Thread()); + tryClose(arena); + return confined; + } + /** * Attempt to close the given Arena. */ @@ -490,5 +832,4 @@ private boolean tryClose(Arena arena) { return false; } } - } From 6749c62b9e4261d25bea477e3c0840ab0ee9c73e Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Fri, 13 Jun 2025 06:55:48 +0000 Subject: [PATCH 039/213] 8358772: Template-Framework Library: Primitive Types Reviewed-by: mhaessig, chagedorn --- .../compiler/lib/template_framework/Hook.java | 2 +- .../lib/template_framework/Template.java | 2 +- .../lib/template_framework/Token.java | 45 +--- .../lib/template_framework/TokenParser.java | 71 +++++++ .../library/CodeGenerationDataNameType.java | 157 ++++++++++++++ .../library/PrimitiveType.java | 151 +++++++++++++ .../examples/TestPrimitiveTypes.java | 201 ++++++++++++++++++ 7 files changed, 585 insertions(+), 44 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/TokenParser.java create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java create mode 100644 test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java b/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java index 48f7852d509..8ee2689eb2f 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Hook.java @@ -75,7 +75,7 @@ public record Hook(String name) { * @return A {@link Token} that captures the anchoring of the scope and the list of validated {@link Token}s. */ public Token anchor(Object... tokens) { - return new HookAnchorToken(this, Token.parse(tokens)); + return new HookAnchorToken(this, TokenParser.parse(tokens)); } /** diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Template.java b/test/hotspot/jtreg/compiler/lib/template_framework/Template.java index f01c5ccffd3..57d06e732bb 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Template.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Template.java @@ -615,7 +615,7 @@ static Template.ThreeArgs make(String arg1Name, String * @throws IllegalArgumentException if the list of tokens contains an unexpected object. */ static TemplateBody body(Object... tokens) { - return new TemplateBody(Token.parse(tokens)); + return new TemplateBody(TokenParser.parse(tokens)); } /** diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/Token.java b/test/hotspot/jtreg/compiler/lib/template_framework/Token.java index dc750c7f79f..0e9f9b272c5 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/Token.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/Token.java @@ -23,17 +23,11 @@ package compiler.lib.template_framework; -import java.util.Arrays; -import java.util.ArrayList; -import java.util.List; - /** * The {@link Template#body} and {@link Hook#anchor} are given a list of tokens, which are either - * {@link Token}s or {@link String}s or some permitted boxed primitives. These are then parsed - * and all non-{@link Token}s are converted to {@link StringToken}s. The parsing also flattens - * {@link List}s. + * {@link Token}s or {@link String}s or some permitted boxed primitives. */ -sealed interface Token permits StringToken, +public sealed interface Token permits StringToken, TemplateToken, TemplateToken.ZeroArgs, TemplateToken.OneArg, @@ -42,37 +36,4 @@ sealed interface Token permits StringToken, HookAnchorToken, HookInsertToken, AddNameToken, - NothingToken -{ - static List parse(Object[] objects) { - if (objects == null) { - throw new IllegalArgumentException("Unexpected tokens: null"); - } - List outputList = new ArrayList<>(); - parseToken(Arrays.asList(objects), outputList); - return outputList; - } - - private static void parseList(List inputList, List outputList) { - for (Object o : inputList) { - parseToken(o, outputList); - } - } - - private static void parseToken(Object o, List outputList) { - if (o == null) { - throw new IllegalArgumentException("Unexpected token: null"); - } - switch (o) { - case Token t -> outputList.add(t); - case String s -> outputList.add(new StringToken(Renderer.format(s))); - case Integer s -> outputList.add(new StringToken(Renderer.format(s))); - case Long s -> outputList.add(new StringToken(Renderer.format(s))); - case Double s -> outputList.add(new StringToken(Renderer.format(s))); - case Float s -> outputList.add(new StringToken(Renderer.format(s))); - case Boolean s -> outputList.add(new StringToken(Renderer.format(s))); - case List l -> parseList(l, outputList); - default -> throw new IllegalArgumentException("Unexpected token: " + o); - } - } -} + NothingToken {} diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/TokenParser.java b/test/hotspot/jtreg/compiler/lib/template_framework/TokenParser.java new file mode 100644 index 00000000000..0c335bd4fb8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/template_framework/TokenParser.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.lib.template_framework; + +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; + +/** + * Helper class for {@link Token}, to keep the parsing methods package private. + * + *

+ * The {@link Template#body} and {@link Hook#anchor} are given a list of tokens, which are either + * {@link Token}s or {@link String}s or some permitted boxed primitives. These are then parsed + * and all non-{@link Token}s are converted to {@link StringToken}s. The parsing also flattens + * {@link List}s. + */ +final class TokenParser { + static List parse(Object[] objects) { + if (objects == null) { + throw new IllegalArgumentException("Unexpected tokens: null"); + } + List outputList = new ArrayList<>(); + parseToken(Arrays.asList(objects), outputList); + return outputList; + } + + private static void parseList(List inputList, List outputList) { + for (Object o : inputList) { + parseToken(o, outputList); + } + } + + private static void parseToken(Object o, List outputList) { + if (o == null) { + throw new IllegalArgumentException("Unexpected token: null"); + } + switch (o) { + case Token t -> outputList.add(t); + case String s -> outputList.add(new StringToken(Renderer.format(s))); + case Integer s -> outputList.add(new StringToken(Renderer.format(s))); + case Long s -> outputList.add(new StringToken(Renderer.format(s))); + case Double s -> outputList.add(new StringToken(Renderer.format(s))); + case Float s -> outputList.add(new StringToken(Renderer.format(s))); + case Boolean s -> outputList.add(new StringToken(Renderer.format(s))); + case List l -> parseList(l, outputList); + default -> throw new IllegalArgumentException("Unexpected token: " + o); + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java new file mode 100644 index 00000000000..56f7afcbaeb --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.lib.template_framework.library; + +import java.util.List; + +import compiler.lib.template_framework.DataName; +import compiler.lib.template_framework.Template; + +/** + * The {@link CodeGenerationDataNameType} extends the {@link DataName.Type} with + * additional functionality for code generation. These types with their extended + * functionality can be used with many other code generation facilities in the + * library, such as generating random {@code Expression}s. + */ +public interface CodeGenerationDataNameType extends DataName.Type { + + /** + * This method provides a random constant value for the type, which can + * be used as a token inside a {@link Template}. + * + * @return A random constant value. + */ + Object con(); + + /** + * The byte {@link PrimitiveType}. + * + * @return The byte {@link PrimitiveType}. + */ + static PrimitiveType bytes() { return PrimitiveType.BYTES; } + + /** + * The short {@link PrimitiveType}. + * + * @return The short {@link PrimitiveType}. + */ + static PrimitiveType shorts() { return PrimitiveType.SHORTS; } + + /** + * The char {@link PrimitiveType}. + * + * @return The char {@link PrimitiveType}. + */ + static PrimitiveType chars() { return PrimitiveType.CHARS; } + + /** + * The int {@link PrimitiveType}. + * + * @return The int {@link PrimitiveType}. + */ + static PrimitiveType ints() { return PrimitiveType.INTS; } + + /** + * The long {@link PrimitiveType}. + * + * @return The long {@link PrimitiveType}. + */ + static PrimitiveType longs() { return PrimitiveType.LONGS; } + + /** + * The float {@link PrimitiveType}. + * + * @return The float {@link PrimitiveType}. + */ + static PrimitiveType floats() { return PrimitiveType.FLOATS; } + + /** + * The double {@link PrimitiveType}. + * + * @return The double {@link PrimitiveType}. + */ + static PrimitiveType doubles() { return PrimitiveType.DOUBLES; } + + /** + * The boolean {@link PrimitiveType}. + * + * @return The boolean {@link PrimitiveType}. + */ + static PrimitiveType booleans() { return PrimitiveType.BOOLEANS; } + + /** + * List of all {@link PrimitiveType}s. + */ + List PRIMITIVE_TYPES = List.of( + bytes(), + chars(), + shorts(), + ints(), + longs(), + floats(), + doubles(), + booleans() + ); + + /** + * List of all integral {@link PrimitiveType}s (byte, char, short, int, long). + */ + List INTEGRAL_TYPES = List.of( + bytes(), + chars(), + shorts(), + ints(), + longs() + ); + + /** + * List of all subword {@link PrimitiveType}s (byte, char, short). + */ + List SUBWORD_TYPES = List.of( + bytes(), + chars(), + shorts() + ); + + /** + * List of all floating {@link PrimitiveType}s (float, double). + */ + List FLOATING_TYPES = List.of( + floats(), + doubles() + ); + + /** + * List of all integral and floating {@link PrimitiveType}s. + */ + List INTEGRAL_AND_FLOATING_TYPES = List.of( + bytes(), + chars(), + shorts(), + ints(), + longs(), + floats(), + doubles() + ); +} diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java new file mode 100644 index 00000000000..3bf6c7f6288 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.lib.template_framework.library; + +import java.util.Random; +import jdk.test.lib.Utils; + +import compiler.lib.generators.Generators; +import compiler.lib.generators.Generator; +import compiler.lib.generators.RestrictableGenerator; + +import compiler.lib.template_framework.DataName; + +/** + * The {@link PrimitiveType} models Java's primitive types, and provides a set + * of useful methods for code generation, such as the {@link #byteSize} and + * {@link #boxedTypeName}. + */ +public final class PrimitiveType implements CodeGenerationDataNameType { + private static final Random RANDOM = Utils.getRandomInstance(); + private static final RestrictableGenerator GEN_BYTE = Generators.G.safeRestrict(Generators.G.ints(), Byte.MIN_VALUE, Byte.MAX_VALUE); + private static final RestrictableGenerator GEN_CHAR = Generators.G.safeRestrict(Generators.G.ints(), Character.MIN_VALUE, Character.MAX_VALUE); + private static final RestrictableGenerator GEN_SHORT = Generators.G.safeRestrict(Generators.G.ints(), Short.MIN_VALUE, Short.MAX_VALUE); + private static final RestrictableGenerator GEN_INT = Generators.G.ints(); + private static final RestrictableGenerator GEN_LONG = Generators.G.longs(); + private static final Generator GEN_DOUBLE = Generators.G.doubles(); + private static final Generator GEN_FLOAT = Generators.G.floats(); + + private static enum Kind { BYTE, SHORT, CHAR, INT, LONG, FLOAT, DOUBLE, BOOLEAN }; + + // We have one static instance each, so we do not have duplicated instances. + static final PrimitiveType BYTES = new PrimitiveType(Kind.BYTE ); + static final PrimitiveType SHORTS = new PrimitiveType(Kind.SHORT ); + static final PrimitiveType CHARS = new PrimitiveType(Kind.CHAR ); + static final PrimitiveType INTS = new PrimitiveType(Kind.INT ); + static final PrimitiveType LONGS = new PrimitiveType(Kind.LONG ); + static final PrimitiveType FLOATS = new PrimitiveType(Kind.FLOAT ); + static final PrimitiveType DOUBLES = new PrimitiveType(Kind.DOUBLE ); + static final PrimitiveType BOOLEANS = new PrimitiveType(Kind.BOOLEAN); + + final Kind kind; + + // Private constructor so nobody can create duplicate instances. + private PrimitiveType(Kind kind) { + this.kind = kind; + } + + @Override + public boolean isSubtypeOf(DataName.Type other) { + return (other instanceof PrimitiveType pt) && pt.kind == kind; + } + + @Override + public String name() { + return switch (kind) { + case BYTE -> "byte"; + case SHORT -> "short"; + case CHAR -> "char"; + case INT -> "int"; + case LONG -> "long"; + case FLOAT -> "float"; + case DOUBLE -> "double"; + case BOOLEAN -> "boolean"; + }; + } + + @Override + public String toString() { + return name(); + } + + public Object con() { + return switch (kind) { + case BYTE -> "(byte)" + GEN_BYTE.next(); + case SHORT -> "(short)" + GEN_SHORT.next(); + case CHAR -> "(char)" + GEN_CHAR.next(); + case INT -> GEN_INT.next(); + case LONG -> GEN_LONG.next(); + case FLOAT -> GEN_FLOAT.next(); + case DOUBLE -> GEN_DOUBLE.next(); + case BOOLEAN -> RANDOM.nextBoolean(); + }; + } + + /** + * Provides the size of the type in bytes. + * + * @return Size of the type in bytes. + * @throws UnsupportedOperationException for boolean which has no defined size. + */ + public int byteSize() { + return switch (kind) { + case BYTE -> 1; + case SHORT, CHAR -> 2; + case INT, FLOAT -> 4; + case LONG, DOUBLE -> 8; + case BOOLEAN -> { throw new UnsupportedOperationException("boolean does not have a defined 'size'"); } + }; + } + + /** + * Provides the name of the boxed type. + * + * @return the name of the boxed type. + */ + public String boxedTypeName() { + return switch (kind) { + case BYTE -> "Byte"; + case SHORT -> "Short"; + case CHAR -> "Character"; + case INT -> "Integer"; + case LONG -> "Long"; + case FLOAT -> "Float"; + case DOUBLE -> "Double"; + case BOOLEAN -> "Boolean"; + }; + } + + /** + * Indicates if the type is a floating point type. + * + * @return true iff the type is a floating point type. + */ + public boolean isFloating() { + return switch (kind) { + case BYTE, SHORT, CHAR, INT, LONG, BOOLEAN -> false; + case FLOAT, DOUBLE -> true; + }; + } +} diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java new file mode 100644 index 00000000000..5cd3f3c2a22 --- /dev/null +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestPrimitiveTypes.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8358772 + * @summary Demonstrate the use of PrimitiveTypes form the Template Library. + * @modules java.base/jdk.internal.misc + * @library /test/lib / + * @compile ../../../compiler/lib/verify/Verify.java + * @run main template_framework.examples.TestPrimitiveTypes + */ + +package template_framework.examples; + +import java.util.List; +import java.util.Map; +import java.util.Collections; +import java.util.HashMap; + +import compiler.lib.compile_framework.*; +import compiler.lib.template_framework.Template; +import compiler.lib.template_framework.TemplateToken; +import static compiler.lib.template_framework.Template.body; +import static compiler.lib.template_framework.Template.dataNames; +import static compiler.lib.template_framework.Template.let; +import static compiler.lib.template_framework.Template.$; +import static compiler.lib.template_framework.Template.addDataName; +import static compiler.lib.template_framework.DataName.Mutability.MUTABLE; + +import compiler.lib.template_framework.library.Hooks; +import compiler.lib.template_framework.library.CodeGenerationDataNameType; +import compiler.lib.template_framework.library.PrimitiveType; + +/** + * This test shows the use of {@link PrimitiveType}. + */ +public class TestPrimitiveTypes { + + public static void main(String[] args) { + // Create a new CompileFramework instance. + CompileFramework comp = new CompileFramework(); + + // Add a java source file. + comp.addJavaSourceCode("p.xyz.InnerTest", generate()); + + // Compile the source file. + comp.compile(); + + // p.xyz.InnerTest.main(); + comp.invoke("p.xyz.InnerTest", "main", new Object[] {}); + } + + // Generate a Java source file as String + public static String generate() { + // Generate a list of test methods. + Map tests = new HashMap<>(); + + // The boxing tests check if we can autobox with "boxedTypeName". + var boxingTemplate = Template.make("name", "type", (String name, PrimitiveType type) -> body( + let("CON1", type.con()), + let("CON2", type.con()), + let("Boxed", type.boxedTypeName()), + """ + public static void #name() { + #type c1 = #CON1; + #type c2 = #CON2; + #Boxed b1 = c1; + #Boxed b2 = c2; + Verify.checkEQ(c1, b1); + Verify.checkEQ(c2, b2); + } + """ + )); + + for (PrimitiveType type : CodeGenerationDataNameType.PRIMITIVE_TYPES) { + String name = "test_boxing_" + type.name(); + tests.put(name, boxingTemplate.asToken(name, type)); + } + + // Integral and Float types have a size. Also test if "isFloating" is correct. + var integralFloatTemplate = Template.make("name", "type", (String name, PrimitiveType type) -> body( + let("size", type.byteSize()), + let("isFloating", type.isFloating()), + """ + public static void #name() { + // Test byteSize via creation of array. + #type[] array = new #type[1]; + MemorySegment ms = MemorySegment.ofArray(array); + if (#size != ms.byteSize()) { + throw new RuntimeException("byteSize mismatch #type"); + } + + // Test isFloating via rounding. + double value = 1.5; + #type rounded = (#type)value; + boolean isFloating = value != rounded; + if (isFloating == #isFloating) { + throw new RuntimeException("isFloating mismatch #type"); + } + } + """ + )); + + for (PrimitiveType type : CodeGenerationDataNameType.INTEGRAL_AND_FLOATING_TYPES) { + String name = "test_integral_floating_" + type.name(); + tests.put(name, integralFloatTemplate.asToken(name, type)); + } + + // Finally, test the type by creating some DataNames (variables), and sampling + // from them. There should be no cross-over between the types. + var variableTemplate = Template.make("type", (PrimitiveType type) -> body( + let("CON", type.con()), + addDataName($("var"), type, MUTABLE), + """ + #type $var = #CON; + """ + )); + + var sampleTemplate = Template.make("type", (PrimitiveType type) -> body( + let("var", dataNames(MUTABLE).exactOf(type).sample().name()), + let("CON", type.con()), + """ + #var = #CON; + """ + )); + + var namesTemplate = Template.make(() -> body( + """ + public static void test_names() { + """, + Hooks.METHOD_HOOK.anchor( + Collections.nCopies(10, + CodeGenerationDataNameType.PRIMITIVE_TYPES.stream().map(type -> + Hooks.METHOD_HOOK.insert(variableTemplate.asToken(type)) + ).toList() + ), + """ + // Now sample: + """, + Collections.nCopies(10, + CodeGenerationDataNameType.PRIMITIVE_TYPES.stream().map(sampleTemplate::asToken).toList() + ) + ), + """ + } + """ + )); + + tests.put("test_names", namesTemplate.asToken()); + + // Finally, put all the tests together in a class, and invoke all + // tests from the main method. + var template = Template.make(() -> body( + """ + package p.xyz; + + import compiler.lib.verify.*; + import java.lang.foreign.MemorySegment; + + public class InnerTest { + public static void main() { + """, + // Call all test methods from main. + tests.keySet().stream().map( + n -> List.of(n, "();\n") + ).toList(), + """ + } + """, + // Now add all the test methods. + tests.values().stream().toList(), + """ + } + """ + )); + + // Render the template to a String. + return template.render(); + } +} From ed39e17e34a2a3fd08a3e54d8d2c309deb99f61a Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 13 Jun 2025 07:45:18 +0000 Subject: [PATCH 040/213] 8359200: Memory corruption in MStack::push Reviewed-by: shade, kvn --- src/hotspot/share/libadt/vectset.cpp | 1 - src/hotspot/share/libadt/vectset.hpp | 1 + src/hotspot/share/opto/block.cpp | 7 +-- src/hotspot/share/opto/block.hpp | 10 +++- src/hotspot/share/opto/matcher.hpp | 9 +-- src/hotspot/share/opto/node.cpp | 5 -- src/hotspot/share/opto/node.hpp | 11 +++- .../arguments/TestOptoNodeListSize.java | 57 +++++++++++++++++++ 8 files changed, 80 insertions(+), 21 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/arguments/TestOptoNodeListSize.java diff --git a/src/hotspot/share/libadt/vectset.cpp b/src/hotspot/share/libadt/vectset.cpp index a4224b0adb1..176660d8302 100644 --- a/src/hotspot/share/libadt/vectset.cpp +++ b/src/hotspot/share/libadt/vectset.cpp @@ -47,7 +47,6 @@ void VectorSet::init(Arena* arena) { // Expand the existing set to a bigger size void VectorSet::grow(uint new_word_capacity) { - _nesting.check(_set_arena); // Check if a potential reallocation in the arena is safe assert(new_word_capacity >= _size, "Should have been checked before, use maybe_grow?"); assert(new_word_capacity < (1U << 30), ""); uint x = next_power_of_2(new_word_capacity); diff --git a/src/hotspot/share/libadt/vectset.hpp b/src/hotspot/share/libadt/vectset.hpp index 9314778e033..7dbe70000c7 100644 --- a/src/hotspot/share/libadt/vectset.hpp +++ b/src/hotspot/share/libadt/vectset.hpp @@ -52,6 +52,7 @@ class VectorSet : public AnyObj { // Grow vector to required word capacity void maybe_grow(uint new_word_capacity) { + _nesting.check(_set_arena); // Check if a potential reallocation in the arena is safe if (new_word_capacity >= _size) { grow(new_word_capacity); } diff --git a/src/hotspot/share/opto/block.cpp b/src/hotspot/share/opto/block.cpp index c33f656047d..e920f6f1fa3 100644 --- a/src/hotspot/share/opto/block.cpp +++ b/src/hotspot/share/opto/block.cpp @@ -37,11 +37,8 @@ #include "utilities/copy.hpp" #include "utilities/powerOfTwo.hpp" -void Block_Array::grow( uint i ) { - _nesting.check(_arena); // Check if a potential reallocation in the arena is safe - if (i < Max()) { - return; // No need to grow - } +void Block_Array::grow(uint i) { + assert(i >= Max(), "Should have been checked before, use maybe_grow?"); DEBUG_ONLY(_limit = i+1); if( i < _size ) return; if( !_size ) { diff --git a/src/hotspot/share/opto/block.hpp b/src/hotspot/share/opto/block.hpp index e6a98c28e77..07faca08dc3 100644 --- a/src/hotspot/share/opto/block.hpp +++ b/src/hotspot/share/opto/block.hpp @@ -53,7 +53,13 @@ class Block_Array : public ArenaObj { ReallocMark _nesting; // Safety checks for arena reallocation protected: Block **_blocks; - void grow( uint i ); // Grow array node to fit + void maybe_grow(uint i) { + _nesting.check(_arena); // Check if a potential reallocation in the arena is safe + if (i >= Max()) { + grow(i); + } + } + void grow(uint i); // Grow array node to fit public: Block_Array(Arena *a) : _size(OptoBlockListSize), _arena(a) { @@ -68,7 +74,7 @@ class Block_Array : public ArenaObj { Block *operator[] ( uint i ) const // Lookup, or assert for not mapped { assert( i < Max(), "oob" ); return _blocks[i]; } // Extend the mapping: index i maps to Block *n. - void map( uint i, Block *n ) { grow(i); _blocks[i] = n; } + void map( uint i, Block *n ) { maybe_grow(i); _blocks[i] = n; } uint Max() const { DEBUG_ONLY(return _limit); return _size; } }; diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index baf43b0d538..2ee2ded17b6 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -65,13 +65,8 @@ class Matcher : public PhaseTransform { Node_Stack::push(n, (uint)ns); } void push(Node *n, Node_State ns, Node *parent, int indx) { - ++_inode_top; - if ((_inode_top + 1) >= _inode_max) grow(); - _inode_top->node = parent; - _inode_top->indx = (uint)indx; - ++_inode_top; - _inode_top->node = n; - _inode_top->indx = (uint)ns; + Node_Stack::push(parent, (uint)indx); + Node_Stack::push(n, (uint)ns); } Node *parent() { pop(); diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index 7633f68ea1e..8f6c67c16f5 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -2798,7 +2798,6 @@ const RegMask &Node::in_RegMask(uint) const { } void Node_Array::grow(uint i) { - _nesting.check(_a); // Check if a potential reallocation in the arena is safe assert(i >= _max, "Should have been checked before, use maybe_grow?"); assert(_max > 0, "invariant"); uint old = _max; @@ -3038,10 +3037,6 @@ void Unique_Node_List::remove_useless_nodes(VectorSet &useful) { //============================================================================= void Node_Stack::grow() { - _nesting.check(_a); // Check if a potential reallocation in the arena is safe - if (_inode_top < _inode_max) { - return; // No need to grow - } size_t old_top = pointer_delta(_inode_top,_inodes,sizeof(INode)); // save _top size_t old_max = pointer_delta(_inode_max,_inodes,sizeof(INode)); size_t max = old_max << 1; // max * 2 diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 843baf48cf8..2bbb10879f5 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -1633,6 +1633,7 @@ class Node_Array : public AnyObj { // Grow array to required capacity void maybe_grow(uint i) { + _nesting.check(_a); // Check if a potential reallocation in the arena is safe if (i >= _max) { grow(i); } @@ -1884,7 +1885,15 @@ class Node_Stack { INode *_inodes; // Array storage for the stack Arena *_a; // Arena to allocate in ReallocMark _nesting; // Safety checks for arena reallocation + + void maybe_grow() { + _nesting.check(_a); // Check if a potential reallocation in the arena is safe + if (_inode_top >= _inode_max) { + grow(); + } + } void grow(); + public: Node_Stack(int size) { size_t max = (size > OptoNodeListSize) ? size : OptoNodeListSize; @@ -1907,7 +1916,7 @@ class Node_Stack { } void push(Node *n, uint i) { ++_inode_top; - grow(); + maybe_grow(); INode *top = _inode_top; // optimization top->node = n; top->indx = i; diff --git a/test/hotspot/jtreg/compiler/arguments/TestOptoNodeListSize.java b/test/hotspot/jtreg/compiler/arguments/TestOptoNodeListSize.java new file mode 100644 index 00000000000..26d04141de2 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arguments/TestOptoNodeListSize.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @library /test/lib / + * @bug 8359200 + * @key randomness + * @requires vm.flagless & vm.compiler2.enabled & vm.debug == true + * @summary Test that -XX:OptoNodeListSize does not crash the VM. + * @run driver compiler.arguments.TestOptoNodeListSize + */ + +package compiler.arguments; + +import java.io.IOException; +import java.util.Random; + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Utils; + +public class TestOptoNodeListSize { + private static final Random RANDOM = Utils.getRandomInstance(); + + public static void main(String[] args) throws IOException { + if (args.length == 0) { + int size = RANDOM.nextInt(1000) + 1; + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:OptoNodeListSize=" + size, + "-Xcomp", "-XX:-TieredCompilation", "compiler.arguments.TestOptoNodeListSize", "run"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } else { + System.out.println("Test passed."); + } + } +} From a8b42848489747f869e33a5067fdda91553eec96 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Fri, 13 Jun 2025 08:01:18 +0000 Subject: [PATCH 041/213] 8359293: Make TestNoNULL extensible Reviewed-by: kbarrett --- test/hotspot/jtreg/sources/TestNoNULL.java | 24 +++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/test/hotspot/jtreg/sources/TestNoNULL.java b/test/hotspot/jtreg/sources/TestNoNULL.java index 12fe46a609e..9c993572aea 100644 --- a/test/hotspot/jtreg/sources/TestNoNULL.java +++ b/test/hotspot/jtreg/sources/TestNoNULL.java @@ -33,6 +33,8 @@ import java.nio.charset.StandardCharsets; import java.nio.file.*; import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -41,11 +43,23 @@ public class TestNoNULL { private static final Set excludedSourceFiles = new HashSet<>(); private static final Set excludedTestFiles = new HashSet<>(); - private static final Set excludedTestExtensions = Set.of(".c", ".java", ".jar", ".class", ".zip"); + private static final Set excludedTestExtensions = extend(new HashSet<>(List.of(".c", ".java", ".jar", ".class", ".zip")), "excludedTestExtensions"); private static final Pattern NULL_PATTERN = Pattern.compile("\\bNULL\\b"); private static Path dir = Paths.get(System.getProperty("test.src")); private static int errorCount = 0; + /** + * Extends {@code toExtend} with the comma separated entries in the value of the + * {@code propertyName} system property. + */ + private static > T extend(T toExtend, String propertyName) { + String extensions = System.getProperty(propertyName); + if (extensions != null) { + toExtend.addAll(List.of(extensions.split(","))); + } + return toExtend; + } + public static void main(String[] args) throws IOException { int maxIter = 20; while (maxIter-- > 0 && dir != null && !Files.exists(dir.resolve("src"))) { @@ -72,15 +86,15 @@ public static void main(String[] args) throws IOException { } private static void initializeExcludedPaths(Path rootDir) { - List sourceExclusions = List.of( + List sourceExclusions = extend(new ArrayList<>(List.of( "src/hotspot/share/prims/jvmti.xml", "src/hotspot/share/prims/jvmti.xsl" - ); + )), "sourceExclusions"); - List testExclusions = List.of( + List testExclusions = extend(new ArrayList<>(List.of( "test/hotspot/jtreg/vmTestbase/nsk/share/jvmti/README", "test/hotspot/jtreg/vmTestbase/nsk/share/jni/README" - ); + )), "testExclusions"); sourceExclusions.forEach(relativePath -> excludedSourceFiles.add(rootDir.resolve(relativePath).normalize().toString())); From 032ead1d905d820f1fe4bf7a49dff98f59a21ded Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 13 Jun 2025 08:03:33 +0000 Subject: [PATCH 042/213] 8358483: G1: Remove G1HeapRegionManager::num_available_regions Reviewed-by: tschatzl, sangheki --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 4 ++++ src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 5 ++--- src/hotspot/share/gc/g1/g1HeapRegionManager.cpp | 4 ---- src/hotspot/share/gc/g1/g1HeapRegionManager.hpp | 2 -- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 705dcd7895b..96dbd0a6a71 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -347,6 +347,10 @@ HeapWord* G1CollectedHeap::humongous_obj_allocate(size_t word_size) { _verifier->verify_region_sets_optional(); uint obj_regions = (uint) humongous_obj_size_in_regions(word_size); + if (obj_regions > num_available_regions()) { + // Can't satisfy this allocation; early-return. + return nullptr; + } // Policy: First try to allocate a humongous object in the free list. G1HeapRegion* humongous_start = _hrm.allocate_humongous(obj_regions); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index fbd1fe6165f..b9e06d0a711 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -969,7 +969,7 @@ class G1CollectedHeap : public CollectedHeap { // Returns true if an incremental GC should be upgrade to a full gc. This // is done when there are no free regions and the heap can't be expanded. bool should_upgrade_to_full_gc() const { - return num_inactive_regions() == 0 && num_free_regions() == 0; + return num_available_regions() == 0; } // The number of inactive regions. @@ -988,13 +988,12 @@ class G1CollectedHeap : public CollectedHeap { uint num_used_regions() const { return _hrm.num_used_regions(); } // The number of regions that can be allocated into. - uint num_available_regions() const { return _hrm.num_available_regions(); } + uint num_available_regions() const { return num_free_regions() + num_inactive_regions(); } MemoryUsage get_auxiliary_data_memory_usage() const { return _hrm.get_auxiliary_data_memory_usage(); } - #ifdef ASSERT bool is_on_master_free_list(G1HeapRegion* hr) { return _hrm.is_free(hr); diff --git a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp index df4786d7fa5..d8c6859c1aa 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionManager.cpp @@ -477,10 +477,6 @@ uint G1HeapRegionManager::find_contiguous_in_free_list(uint num_regions) { } uint G1HeapRegionManager::find_contiguous_allow_expand(uint num_regions) { - // Check if we can actually satisfy the allocation. - if (num_regions > num_available_regions()) { - return G1_NO_HRM_INDEX; - } // Find any candidate. return find_contiguous_in_range(0, max_num_regions(), num_regions); } diff --git a/src/hotspot/share/gc/g1/g1HeapRegionManager.hpp b/src/hotspot/share/gc/g1/g1HeapRegionManager.hpp index 4429384bcc5..19ae9887e94 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionManager.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionManager.hpp @@ -239,8 +239,6 @@ class G1HeapRegionManager: public CHeapObj { // The number of regions reserved for the heap. uint max_num_regions() const { return (uint)_regions.length(); } - uint num_available_regions() const { return num_free_regions() + num_inactive_regions(); } - MemoryUsage get_auxiliary_data_memory_usage() const; MemRegion reserved() const { return MemRegion(heap_bottom(), heap_end()); } From a0fb35c8379295d2927c18d694ea52f7b7488a2b Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Fri, 13 Jun 2025 08:46:12 +0000 Subject: [PATCH 043/213] 8359272: Several vmTestbase/compact tests timed out on large memory machine Reviewed-by: tschatzl, ayang --- .../gc/compact/Compact_InternedStrings/TestDescription.java | 4 +++- .../TestDescription.java | 4 +++- .../gc/compact/Compact_Strings_ArrayOf/TestDescription.java | 4 +++- .../gc/compact/Humongous_InternedStrings/TestDescription.java | 4 +++- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings/TestDescription.java index 8d28df3c457..657cb68edc7 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,9 +34,11 @@ * This testcase uses interned strings for both first and second phases * and multiple threads. * + * @requires os.maxMemory > 3G * @library /vmTestbase * /test/lib * @run main/othervm + * -Xmx2G * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp interned(randomString) diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_NonbranchyTree/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_NonbranchyTree/TestDescription.java index 1aaeb2fc84d..b0771871a56 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_NonbranchyTree/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_InternedStrings_NonbranchyTree/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,9 +34,11 @@ * This testcase uses interned strings for first phase, * random arrays for second phases and multiple threads. * + * @requires os.maxMemory > 3G * @library /vmTestbase * /test/lib * @run main/othervm + * -Xmx2G * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp interned(randomString) diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_ArrayOf/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_ArrayOf/TestDescription.java index f54f006d4aa..ea942c7be07 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_ArrayOf/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Compact_Strings_ArrayOf/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,9 +34,11 @@ * This testcase uses random strings for first phase, array of * random strings for second phase and multiple threads. * + * @requires os.maxMemory > 3G * @library /vmTestbase * /test/lib * @run main/othervm + * -Xmx2G * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp randomString diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_InternedStrings/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_InternedStrings/TestDescription.java index b155c081eea..41c2b0ae4d0 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_InternedStrings/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_InternedStrings/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,9 +34,11 @@ * This testcase uses interned strings for both first and second phases * and multiple threads. * + * @requires os.maxMemory > 3G * @library /vmTestbase * /test/lib * @run main/othervm + * -Xmx2G * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp interned(randomString) From e7f63ba3109adf614cee1bc392cfeef85e9ca778 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Fri, 13 Jun 2025 09:01:09 +0000 Subject: [PATCH 044/213] 8359327: Incorrect AVX3Threshold results into code buffer overflows on APX targets Reviewed-by: sviswanathan --- src/hotspot/cpu/x86/stubDeclarations_x86.hpp | 2 +- src/hotspot/cpu/x86/vm_version_x86.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp index dcb919ddcd0..2ca05bc773e 100644 --- a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp +++ b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp @@ -239,7 +239,7 @@ do_arch_blob, \ do_arch_entry, \ do_arch_entry_init) \ - do_arch_blob(final, 31000 \ + do_arch_blob(final, 33000 \ WINDOWS_ONLY(+22000) ZGC_ONLY(+20000)) \ #endif // CPU_X86_STUBDECLARATIONS_HPP diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 152866e65f3..e4a101a5977 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -2111,7 +2111,7 @@ bool VM_Version::is_intel_cascade_lake() { // has improved implementation of 64-byte load/stores and so the default // threshold is set to 0 for these platforms. int VM_Version::avx3_threshold() { - return (is_intel_family_core() && + return (is_intel_server_family() && supports_serialize() && FLAG_IS_DEFAULT(AVX3Threshold)) ? 0 : AVX3Threshold; } From 3a1887269b9cecf9dea68637f99b0b103baafbdb Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Fri, 13 Jun 2025 09:12:02 +0000 Subject: [PATCH 045/213] 8359225: Remove unused test/jdk/javax/script/MyContext.java Reviewed-by: sundar --- test/jdk/javax/script/MyContext.java | 222 --------------------------- 1 file changed, 222 deletions(-) delete mode 100644 test/jdk/javax/script/MyContext.java diff --git a/test/jdk/javax/script/MyContext.java b/test/jdk/javax/script/MyContext.java deleted file mode 100644 index c0014460b69..00000000000 --- a/test/jdk/javax/script/MyContext.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. - * 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. - */ - -/* - * This is pluggable context used by test for 6398614 - */ - -import javax.script.*; -import java.util.*; -import java.io.*; - -public class MyContext implements ScriptContext { - - public static final int APP_SCOPE = 125; - - protected Writer writer; - - protected Writer errorWriter; - - protected Reader reader; - - - protected Bindings appScope; - protected Bindings engineScope; - protected Bindings globalScope; - - - public MyContext() { - appScope = new SimpleBindings(); - engineScope = new SimpleBindings(); - globalScope = null; - reader = new InputStreamReader(System.in); - writer = new PrintWriter(System.out , true); - errorWriter = new PrintWriter(System.err, true); - } - - public void setBindings(Bindings bindings, int scope) { - - switch (scope) { - case APP_SCOPE: - if (bindings == null) { - throw new NullPointerException("App scope cannot be null."); - } - appScope = bindings; - break; - - case ENGINE_SCOPE: - if (bindings == null) { - throw new NullPointerException("Engine scope cannot be null."); - } - engineScope = bindings; - break; - case GLOBAL_SCOPE: - globalScope = bindings; - break; - default: - throw new IllegalArgumentException("Invalid scope value."); - } - } - - public Object getAttribute(String name) { - if (engineScope.containsKey(name)) { - return getAttribute(name, ENGINE_SCOPE); - } else if (appScope.containsKey(name)) { - return getAttribute(name, APP_SCOPE); - } else if (globalScope != null && globalScope.containsKey(name)) { - return getAttribute(name, GLOBAL_SCOPE); - } - - return null; - } - - public Object getAttribute(String name, int scope) { - - switch (scope) { - case APP_SCOPE: - return appScope.get(name); - - case ENGINE_SCOPE: - return engineScope.get(name); - - case GLOBAL_SCOPE: - if (globalScope != null) { - return globalScope.get(name); - } - return null; - - default: - throw new IllegalArgumentException("Illegal scope value."); - } - } - - public Object removeAttribute(String name, int scope) { - - switch (scope) { - case APP_SCOPE: - if (getBindings(APP_SCOPE) != null) { - return getBindings(APP_SCOPE).remove(name); - } - return null; - - - case ENGINE_SCOPE: - if (getBindings(ENGINE_SCOPE) != null) { - return getBindings(ENGINE_SCOPE).remove(name); - } - return null; - - case GLOBAL_SCOPE: - if (getBindings(GLOBAL_SCOPE) != null) { - return getBindings(GLOBAL_SCOPE).remove(name); - } - return null; - - default: - throw new IllegalArgumentException("Illegal scope value."); - } - } - - public void setAttribute(String name, Object value, int scope) { - - switch (scope) { - case APP_SCOPE: - appScope.put(name, value); - return; - - case ENGINE_SCOPE: - engineScope.put(name, value); - return; - - case GLOBAL_SCOPE: - if (globalScope != null) { - globalScope.put(name, value); - } - return; - - default: - throw new IllegalArgumentException("Illegal scope value."); - } - } - - public Writer getWriter() { - return writer; - } - - public Reader getReader() { - return reader; - } - - public void setReader(Reader reader) { - this.reader = reader; - } - - public void setWriter(Writer writer) { - this.writer = writer; - } - - public Writer getErrorWriter() { - return errorWriter; - } - - public void setErrorWriter(Writer writer) { - this.errorWriter = writer; - } - - public int getAttributesScope(String name) { - if (engineScope.containsKey(name)) { - return ENGINE_SCOPE; - } else if (appScope.containsKey(name)) { - return APP_SCOPE; - } else if (globalScope != null && globalScope.containsKey(name)) { - return GLOBAL_SCOPE; - } else { - return -1; - } - } - - public Bindings getBindings(int scope) { - if (scope == ENGINE_SCOPE) { - return engineScope; - } else if (scope == APP_SCOPE) { - return appScope; - } else if (scope == GLOBAL_SCOPE) { - return globalScope; - } else { - throw new IllegalArgumentException("Illegal scope value."); - } - } - - public List getScopes() { - return scopes; - } - - private static List scopes; - static { - scopes = new ArrayList(3); - scopes.add(ENGINE_SCOPE); - scopes.add(APP_SCOPE); - scopes.add(GLOBAL_SCOPE); - scopes = Collections.unmodifiableList(scopes); - } -} From ead4529c9219009fc4224e52e9ac4af5055e7137 Mon Sep 17 00:00:00 2001 From: Prateek Nima Date: Fri, 13 Jun 2025 10:32:50 +0000 Subject: [PATCH 046/213] 8340182: Java HttpClient does not follow default retry limit of 3 retries Reviewed-by: dfuchs --- .../share/classes/module-info.java | 3 +- .../HttpClientAuthRetryLimitTest.java | 134 ++++++++++++++++++ 2 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 test/jdk/java/net/httpclient/HttpClientAuthRetryLimitTest.java diff --git a/src/java.net.http/share/classes/module-info.java b/src/java.net.http/share/classes/module-info.java index 7d7c3fb351a..14cbb85291d 100644 --- a/src/java.net.http/share/classes/module-info.java +++ b/src/java.net.http/share/classes/module-info.java @@ -156,7 +156,8 @@ * *

  • {@systemProperty jdk.httpclient.auth.retrylimit} (default: 3)
    * The number of attempts the Basic authentication filter will attempt to retry a failed - * authentication. + * authentication. The number of authentication attempts is always one greater than the + * retry limit, as the initial request does not count toward the retries. *

  • *
  • {@systemProperty jdk.httpclient.sendBufferSize} (default: operating system * default)
    The HTTP client {@linkplain java.nio.channels.SocketChannel socket} diff --git a/test/jdk/java/net/httpclient/HttpClientAuthRetryLimitTest.java b/test/jdk/java/net/httpclient/HttpClientAuthRetryLimitTest.java new file mode 100644 index 00000000000..818fd8c7a01 --- /dev/null +++ b/test/jdk/java/net/httpclient/HttpClientAuthRetryLimitTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 8340182 + * @summary Auth retry limit system property + * @library /test/lib /test/jdk/java/net/httpclient/lib + * @build jdk.httpclient.test.lib.http2.Http2TestServer + * @run junit HttpClientAuthRetryLimitTest + * @run junit/othervm -Djdk.httpclient.auth.retrylimit=1 HttpClientAuthRetryLimitTest + * @run junit/othervm -Djdk.httpclient.auth.retrylimit=0 HttpClientAuthRetryLimitTest + * @run junit/othervm -Djdk.httpclient.auth.retrylimit=-1 HttpClientAuthRetryLimitTest + */ + +import jdk.httpclient.test.lib.common.HttpServerAdapters; +import jdk.test.lib.net.SimpleSSLContext; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import javax.net.ssl.SSLContext; +import java.io.IOException; +import java.net.Authenticator; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class HttpClientAuthRetryLimitTest implements HttpServerAdapters { + + private static final SSLContext SSL_CONTEXT = createSslContext(); + + private static SSLContext createSslContext() { + try { + return new SimpleSSLContext().get(); + } catch (IOException exception) { + throw new RuntimeException(exception); + } + } + + // This is the system default value for jdk.httpclient.auth.retrylimit + private static final int DEFAULT_RETRY_LIMIT = 3; + private static final int RETRY_LIMIT = Integer.getInteger( + "jdk.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT); + + private static Stream args() { + return Stream.of( + HttpClient.Version.HTTP_1_1, + HttpClient.Version.HTTP_2) + .flatMap(version -> Stream + .of(false, true) + .map(secure -> Arguments.of(version, secure))); + } + + private static HttpClient.Builder createClient(boolean secure) { + HttpClient.Builder builder = HttpClient.newBuilder(); + if (secure) { + builder.sslContext(SSL_CONTEXT); + } + return builder; + } + + @ParameterizedTest + @MethodSource("args") + void testDefaultSystemProperty(HttpClient.Version version, boolean secure) throws Exception { + + AtomicInteger requestCount = new AtomicInteger(0); + + try (HttpTestServer httpTestServer = ((secure)? HttpTestServer.create( + version, SSL_CONTEXT): HttpTestServer.create(version))) { + final String requestUriScheme = secure ? "https" : "http"; + final String requestPath = "/" + this.getClass().getSimpleName() + "/"; + final String uriString = "://" + httpTestServer.serverAuthority() + requestPath; + final URI requestUri = URI.create(requestUriScheme + uriString); + + HttpTestHandler httpTestHandler = t -> { + t.getResponseHeaders() + .addHeader("WWW-Authenticate", "Basic realm=\"Test\""); + t.sendResponseHeaders(401,0); + }; + + httpTestServer.addHandler(httpTestHandler, requestPath); + httpTestServer.start(); + try ( + HttpClient client = createClient(secure) + .authenticator(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + requestCount.incrementAndGet(); + return new PasswordAuthentication("username", "password".toCharArray()); + } + }) + .build()) { + HttpRequest request = HttpRequest.newBuilder().version(version) + .GET() + .uri(requestUri) + .build(); + IOException exception = assertThrows(IOException.class, () -> client.send( + request, HttpResponse.BodyHandlers.discarding())); + assertEquals("too many authentication attempts. Limit: " + RETRY_LIMIT, exception.getMessage()); + int totalRequestCount = requestCount.get(); + assertEquals(totalRequestCount, Math.max(RETRY_LIMIT, 0) + 1); + } + } + } +} From 25b22c9b553ffab82eb44df23f6b4942724aedaf Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 13 Jun 2025 10:47:26 +0000 Subject: [PATCH 047/213] 8358602: JFR: Annotations in jdk.jfr package should not use "not null" in specification Reviewed-by: mgronlun --- src/jdk.jfr/share/classes/jdk/jfr/DataAmount.java | 4 ++-- src/jdk.jfr/share/classes/jdk/jfr/Description.java | 4 ++-- src/jdk.jfr/share/classes/jdk/jfr/Label.java | 4 ++-- src/jdk.jfr/share/classes/jdk/jfr/Period.java | 4 ++-- src/jdk.jfr/share/classes/jdk/jfr/Threshold.java | 4 ++-- src/jdk.jfr/share/classes/jdk/jfr/Throttle.java | 2 +- src/jdk.jfr/share/classes/jdk/jfr/Timespan.java | 4 ++-- src/jdk.jfr/share/classes/jdk/jfr/Timestamp.java | 4 ++-- 8 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/DataAmount.java b/src/jdk.jfr/share/classes/jdk/jfr/DataAmount.java index c2442ad2c92..106110f0208 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/DataAmount.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/DataAmount.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,7 @@ /** * Returns the unit for the data amount, by default bytes. * - * @return the data amount unit, default {@code BYTES}, not {@code null} + * @return the data amount unit, default {@code BYTES} */ String value() default BYTES; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Description.java b/src/jdk.jfr/share/classes/jdk/jfr/Description.java index f907c25d4d0..d34312fc918 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Description.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Description.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ /** * Returns a sentence or two that describes the annotated element. * - * @return a description, not {@code null} + * @return a description */ String value(); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Label.java b/src/jdk.jfr/share/classes/jdk/jfr/Label.java index 6a4928e0a04..6f5d85380df 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Label.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Label.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ /** * Returns a human-readable name for the annotated element. * - * @return a human-readable name, not {@code null} + * @return a human-readable name */ String value(); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Period.java b/src/jdk.jfr/share/classes/jdk/jfr/Period.java index 90c4a9699d8..97d4676e6a5 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Period.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Period.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ * least once for every recording file. The number of events that are emitted * depends on how many times the file rotations occur when data is recorded. * - * @return the default setting value, not {@code null} + * @return the default setting value, default {@code "everyChunk"} */ String value() default "everyChunk"; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Threshold.java b/src/jdk.jfr/share/classes/jdk/jfr/Threshold.java index 94030fba7b2..92c40823bbb 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Threshold.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Threshold.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ *

    * Example values are {@code "0 ns"}, {@code "10 ms"}, and {@code "1 s"}. * - * @return the threshold, default {@code "0 ns"}, not {@code null} + * @return the threshold, default {@code "0 ns"} */ String value() default "0 ns"; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Throttle.java b/src/jdk.jfr/share/classes/jdk/jfr/Throttle.java index 7b9771eba2b..7278a93a698 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Throttle.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Throttle.java @@ -74,7 +74,7 @@ *

    * Specifying {@code "off"} (case-sensitive) results in all events being emitted. * - * @return the throttle value, default {@code "off"} not {@code null} + * @return the throttle value, default {@code "off"} */ String value() default "off"; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Timespan.java b/src/jdk.jfr/share/classes/jdk/jfr/Timespan.java index bc5ac72d045..f82ae42b762 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Timespan.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Timespan.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ *

    * By default, the unit is nanoseconds. * - * @return the time span unit, default {@link #NANOSECONDS}, not {@code null} + * @return the time span unit, default {@code NANOSECONDS} */ String value() default NANOSECONDS; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/Timestamp.java b/src/jdk.jfr/share/classes/jdk/jfr/Timestamp.java index d13f5151ea1..11b4ed9c966 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/Timestamp.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/Timestamp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ /** * Unit for the time stamp. * - * @return time stamp unit, not {@code null} + * @return time stamp unit, default {@code MILLISECONDS_SINCE_EPOCH} */ String value() default Timestamp.MILLISECONDS_SINCE_EPOCH; } From e8ef93ae9de624f25166bdf010c915672b2c5cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Fri, 13 Jun 2025 11:16:36 +0000 Subject: [PATCH 048/213] 8357782: JVM JIT Causes Static Initialization Order Issue Co-authored-by: Tobias Hartmann Reviewed-by: thartmann, dlong, dfenacci --- src/hotspot/share/c1/c1_ValueMap.hpp | 10 ++- src/hotspot/share/ci/ciInstanceKlass.cpp | 5 ++ src/hotspot/share/ci/ciInstanceKlass.hpp | 2 + .../c1/TestStaticInitializerSideEffect.java | 69 +++++++++++++++++++ 4 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c1/TestStaticInitializerSideEffect.java diff --git a/src/hotspot/share/c1/c1_ValueMap.hpp b/src/hotspot/share/c1/c1_ValueMap.hpp index 12c372f27c8..6583a07c920 100644 --- a/src/hotspot/share/c1/c1_ValueMap.hpp +++ b/src/hotspot/share/c1/c1_ValueMap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,7 +187,13 @@ class ValueNumberingVisitor: public InstructionVisitor { void do_Convert (Convert* x) { /* nothing to do */ } void do_NullCheck (NullCheck* x) { /* nothing to do */ } void do_TypeCast (TypeCast* x) { /* nothing to do */ } - void do_NewInstance (NewInstance* x) { /* nothing to do */ } + void do_NewInstance (NewInstance* x) { + ciInstanceKlass* c = x->klass(); + if (c != nullptr && !c->is_initialized() && + (!c->is_loaded() || c->has_class_initializer())) { + kill_memory(); + } + } void do_NewTypeArray (NewTypeArray* x) { /* nothing to do */ } void do_NewObjectArray (NewObjectArray* x) { /* nothing to do */ } void do_NewMultiArray (NewMultiArray* x) { /* nothing to do */ } diff --git a/src/hotspot/share/ci/ciInstanceKlass.cpp b/src/hotspot/share/ci/ciInstanceKlass.cpp index a24a68f874b..c367170f2c2 100644 --- a/src/hotspot/share/ci/ciInstanceKlass.cpp +++ b/src/hotspot/share/ci/ciInstanceKlass.cpp @@ -549,6 +549,11 @@ bool ciInstanceKlass::compute_has_trusted_loader() { return java_lang_ClassLoader::is_trusted_loader(loader_oop); } +bool ciInstanceKlass::has_class_initializer() { + VM_ENTRY_MARK; + return get_instanceKlass()->class_initializer() != nullptr; +} + // ------------------------------------------------------------------ // ciInstanceKlass::find_method // diff --git a/src/hotspot/share/ci/ciInstanceKlass.hpp b/src/hotspot/share/ci/ciInstanceKlass.hpp index 92a7434e8ba..d3d988e8735 100644 --- a/src/hotspot/share/ci/ciInstanceKlass.hpp +++ b/src/hotspot/share/ci/ciInstanceKlass.hpp @@ -231,6 +231,8 @@ class ciInstanceKlass : public ciKlass { ciInstanceKlass* unique_concrete_subklass(); bool has_finalizable_subclass(); + bool has_class_initializer(); + bool contains_field_offset(int offset); // Get the instance of java.lang.Class corresponding to diff --git a/test/hotspot/jtreg/compiler/c1/TestStaticInitializerSideEffect.java b/test/hotspot/jtreg/compiler/c1/TestStaticInitializerSideEffect.java new file mode 100644 index 00000000000..4dd051afa43 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c1/TestStaticInitializerSideEffect.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Test that C1 respects that static initializers can have memory side effects. + * @bug 8357782 + * @requires vm.compiler1.enabled + * @comment Since static initializers only execute in the first execution of the class initializer, we need -Xcomp. + * @run main/othervm -Xcomp -XX:TieredStopAtLevel=1 -XX:CompileCommand=compileonly,compiler/c1/A$B.test compiler.c1.TestStaticInitializerSideEffect + */ + +package compiler.c1; + +public class TestStaticInitializerSideEffect { + public static void main(String[] args) { + A.B.test(); + } +} + +class A { + static class B { + static String field; + + static void test() { + // This unused variable triggers local value numbering to remove + // the field load in the constructor below if it is not killed + // before. + String tmp = field; + // The class initializer of C should kill the LVN effect of tmp due + // to the memory side effects of the static initializer. + new C(field); + } + } + + static class C { + // When executing the class initializer, this has a side effect. + static { + B.field = "Hello"; + } + + C(String val) { + // If C1 does not respect that side effect, we crash here. + if (val == null) { + throw new RuntimeException("Should not reach here"); + } + } + } +} From b5334fe23797a81b91a558f9e55cdcaaee61d37b Mon Sep 17 00:00:00 2001 From: Sean Mullan Date: Fri, 13 Jun 2025 12:15:27 +0000 Subject: [PATCH 049/213] 8314180: Disable XPath in XML Signatures Reviewed-by: weijun --- src/java.base/share/conf/security/java.security | 1 + test/jdk/javax/xml/crypto/dsig/GenerationTests.java | 6 +++--- test/jdk/javax/xml/crypto/dsig/HereFunction.java | 6 +++--- test/jdk/javax/xml/crypto/dsig/SecureValidationPolicy.java | 7 ++++--- test/jdk/javax/xml/crypto/dsig/ValidationTests.java | 6 +++--- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 61e8aaaf6d1..5d96d74539e 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -1012,6 +1012,7 @@ jdk.xml.dsig.secureValidationPolicy=\ disallowAlg http://www.w3.org/2000/09/xmldsig#rsa-sha1,\ disallowAlg http://www.w3.org/2007/05/xmldsig-more#sha1-rsa-MGF1,\ disallowAlg http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1,\ + disallowAlg http://www.w3.org/TR/1999/REC-xpath-19991116,\ maxTransforms 5,\ maxReferences 30,\ disallowReferenceUriSchemes file http https,\ diff --git a/test/jdk/javax/xml/crypto/dsig/GenerationTests.java b/test/jdk/javax/xml/crypto/dsig/GenerationTests.java index 668a5a50a0a..ac24ceb476c 100644 --- a/test/jdk/javax/xml/crypto/dsig/GenerationTests.java +++ b/test/jdk/javax/xml/crypto/dsig/GenerationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -286,8 +286,8 @@ private static enum KeyInfoType { private static boolean result = true; public static void main(String args[]) throws Exception { - // Re-enable sha1 algs - SecurityUtils.removeAlgsFromDSigPolicy("sha1"); + // Re-enable sha1 and xpath algs + SecurityUtils.removeAlgsFromDSigPolicy("sha1", "xpath"); setup(); test_context_iterator(); diff --git a/test/jdk/javax/xml/crypto/dsig/HereFunction.java b/test/jdk/javax/xml/crypto/dsig/HereFunction.java index 4910d0e6a89..100c89ea142 100644 --- a/test/jdk/javax/xml/crypto/dsig/HereFunction.java +++ b/test/jdk/javax/xml/crypto/dsig/HereFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,8 +85,8 @@ public static void main(String args[]) throws Throwable { if (!args[0].equals("default")) { Security.setProperty("jdk.xml.dsig.hereFunctionSupported", args[0]); } - // Re-enable sha1 algs - SecurityUtils.removeAlgsFromDSigPolicy("sha1"); + // Re-enable sha1 and xpath algs + SecurityUtils.removeAlgsFromDSigPolicy("sha1", "xpath"); boolean expected = Boolean.parseBoolean(args[1]); diff --git a/test/jdk/javax/xml/crypto/dsig/SecureValidationPolicy.java b/test/jdk/javax/xml/crypto/dsig/SecureValidationPolicy.java index e55d1460ce7..15f8fcf6dac 100644 --- a/test/jdk/javax/xml/crypto/dsig/SecureValidationPolicy.java +++ b/test/jdk/javax/xml/crypto/dsig/SecureValidationPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /** * @test - * @bug 8151893 8259709 + * @bug 8151893 8259709 8314180 * @summary Tests for the jdk.xml.dsig.secureValidationPolicy security property * @modules java.xml.crypto/org.jcp.xml.dsig.internal.dom */ @@ -47,7 +47,8 @@ public static void main(String[] args) throws Exception { "http://www.w3.org/2000/09/xmldsig#dsa-sha1", "http://www.w3.org/2000/09/xmldsig#rsa-sha1", "http://www.w3.org/2007/05/xmldsig-more#sha1-rsa-MGF1", - "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"); + "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", + "http://www.w3.org/TR/1999/REC-xpath-19991116"); // Test expected defaults System.out.println("Testing defaults"); diff --git a/test/jdk/javax/xml/crypto/dsig/ValidationTests.java b/test/jdk/javax/xml/crypto/dsig/ValidationTests.java index b5e093a44d8..49a19824162 100644 --- a/test/jdk/javax/xml/crypto/dsig/ValidationTests.java +++ b/test/jdk/javax/xml/crypto/dsig/ValidationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -141,8 +141,8 @@ static class Test { }; public static void main(String args[]) throws Exception { - // Re-enable sha1 algs - SecurityUtils.removeAlgsFromDSigPolicy("sha1"); + // Re-enable sha1 and xpath algs + SecurityUtils.removeAlgsFromDSigPolicy("sha1", "xpath"); httpUd = new HttpURIDereferencer(); From b4c4496ef8013df25b6368bdebf082d223d6afed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Fri, 13 Jun 2025 13:02:27 +0000 Subject: [PATCH 050/213] 8354196: C2: reorder and capitalize phase definition Reviewed-by: chagedorn, mchevalier --- src/hotspot/share/opto/phasetype.hpp | 66 +++---- .../lib/ir_framework/CompilePhase.java | 177 +++++++++--------- 2 files changed, 122 insertions(+), 121 deletions(-) diff --git a/src/hotspot/share/opto/phasetype.hpp b/src/hotspot/share/opto/phasetype.hpp index 2546b319762..517f0aa72c7 100644 --- a/src/hotspot/share/opto/phasetype.hpp +++ b/src/hotspot/share/opto/phasetype.hpp @@ -47,12 +47,15 @@ flags(EXPAND_VBOX, "Expand VectorBox") \ flags(ELIMINATE_VBOX_ALLOC, "Eliminate VectorBoxAllocate") \ flags(ITER_GVN_BEFORE_EA, "Iter GVN before EA") \ - flags(ITER_GVN_AFTER_VECTOR, "Iter GVN after vector box elimination") \ + flags(ITER_GVN_AFTER_VECTOR, "Iter GVN after Vector Box Elimination") \ flags(BEFORE_LOOP_OPTS, "Before Loop Optimizations") \ - flags(BEFORE_BEAUTIFY_LOOPS, "Before beautify loops") \ - flags(AFTER_BEAUTIFY_LOOPS, "After beautify loops") \ - flags(BEFORE_LOOP_UNROLLING, "Before Loop Unrolling") \ - flags(AFTER_LOOP_UNROLLING, "After Loop Unrolling") \ + flags(PHASEIDEAL_BEFORE_EA, "PhaseIdealLoop before EA") \ + flags(AFTER_EA, "After Escape Analysis") \ + flags(ITER_GVN_AFTER_EA, "Iter GVN after EA") \ + flags(BEFORE_BEAUTIFY_LOOPS, "Before Beautify Loops") \ + flags(AFTER_BEAUTIFY_LOOPS, "After Beautify Loops") \ + flags(BEFORE_CLOOPS, "Before CountedLoop") \ + flags(AFTER_CLOOPS, "After CountedLoop") \ flags(BEFORE_SPLIT_IF, "Before Split-If") \ flags(AFTER_SPLIT_IF, "After Split-If") \ flags(BEFORE_LOOP_PREDICATION_IC, "Before Loop Predication IC") \ @@ -69,22 +72,19 @@ flags(AFTER_LOOP_MULTIVERSIONING, "After Loop Multiversioning") \ flags(BEFORE_RANGE_CHECK_ELIMINATION, "Before Range Check Elimination") \ flags(AFTER_RANGE_CHECK_ELIMINATION, "After Range Check Elimination") \ + flags(ITER_GVN_AFTER_ELIMINATION, "Iter GVN after Eliminating Allocations and Locks") \ flags(BEFORE_PRE_MAIN_POST, "Before Pre/Main/Post Loops") \ flags(AFTER_PRE_MAIN_POST, "After Pre/Main/Post Loops") \ - flags(AUTO_VECTORIZATION1_BEFORE_APPLY, "AutoVectorization 1, Before Apply") \ - flags(AUTO_VECTORIZATION2_AFTER_REORDER, "AutoVectorization 2, After Apply Memop Reordering") \ - flags(AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT, "AutoVectorization 3, After Adjusting Pre-Loop Limit") \ - flags(AUTO_VECTORIZATION4_AFTER_SPECULATIVE_RUNTIME_CHECKS, "AutoVectorization 4, After Adding Speculative Runtime Checks") \ - flags(AUTO_VECTORIZATION5_AFTER_APPLY, "AutoVectorization 5, After Apply") \ - flags(BEFORE_CLOOPS, "Before CountedLoop") \ - flags(AFTER_CLOOPS, "After CountedLoop") \ - flags(PHASEIDEAL_BEFORE_EA, "PhaseIdealLoop before EA") \ - flags(AFTER_EA, "After Escape Analysis") \ - flags(ITER_GVN_AFTER_EA, "Iter GVN after EA") \ - flags(ITER_GVN_AFTER_ELIMINATION, "Iter GVN after eliminating allocations and locks") \ + flags(BEFORE_LOOP_UNROLLING, "Before Loop Unrolling") \ + flags(AFTER_LOOP_UNROLLING, "After Loop Unrolling") \ flags(PHASEIDEALLOOP1, "PhaseIdealLoop 1") \ flags(PHASEIDEALLOOP2, "PhaseIdealLoop 2") \ flags(PHASEIDEALLOOP3, "PhaseIdealLoop 3") \ + flags(AUTO_VECTORIZATION1_BEFORE_APPLY, "AutoVectorization 1, before Apply") \ + flags(AUTO_VECTORIZATION2_AFTER_REORDER, "AutoVectorization 2, after Apply Memop Reordering") \ + flags(AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT, "AutoVectorization 3, after Adjusting Pre-loop Limit") \ + flags(AUTO_VECTORIZATION4_AFTER_SPECULATIVE_RUNTIME_CHECKS, "AutoVectorization 4, after Adding Speculative Runtime Checks") \ + flags(AUTO_VECTORIZATION5_AFTER_APPLY, "AutoVectorization 5, after Apply") \ flags(BEFORE_CCP1, "Before PhaseCCP 1") \ flags(CCP1, "PhaseCCP 1") \ flags(ITER_GVN2, "Iter GVN 2") \ @@ -94,26 +94,26 @@ flags(BEFORE_MACRO_EXPANSION , "Before Macro Expansion") \ flags(AFTER_MACRO_EXPANSION_STEP, "After Macro Expansion Step") \ flags(AFTER_MACRO_EXPANSION, "After Macro Expansion") \ - flags(BARRIER_EXPANSION, "Barrier expand") \ - flags(OPTIMIZE_FINISHED, "Optimize finished") \ - flags(BEFORE_MATCHING, "Before matching") \ - flags(MATCHING, "After matching") \ - flags(GLOBAL_CODE_MOTION, "Global code motion") \ - flags(INITIAL_LIVENESS, "Initial liveness") \ - flags(LIVE_RANGE_STRETCHING, "Live range stretching") \ - flags(AGGRESSIVE_COALESCING, "Aggressive coalescing") \ - flags(INITIAL_SPILLING, "Initial spilling") \ - flags(CONSERVATIVE_COALESCING, "Conservative coalescing") \ - flags(ITERATIVE_SPILLING, "Iterative spilling") \ - flags(AFTER_ITERATIVE_SPILLING, "After iterative spilling") \ - flags(POST_ALLOCATION_COPY_REMOVAL, "Post-allocation copy removal") \ - flags(MERGE_MULTI_DEFS, "Merge multiple definitions") \ - flags(FIX_UP_SPILLS, "Fix up spills") \ + flags(BARRIER_EXPANSION, "Barrier Expand") \ + flags(OPTIMIZE_FINISHED, "Optimize Finished") \ + flags(BEFORE_MATCHING, "Before Matching") \ + flags(MATCHING, "After Matching") \ + flags(GLOBAL_CODE_MOTION, "Global Code Motion") \ + flags(INITIAL_LIVENESS, "Initial Liveness") \ + flags(LIVE_RANGE_STRETCHING, "Live Range Stretching") \ + flags(AGGRESSIVE_COALESCING, "Aggressive Coalescing") \ + flags(INITIAL_SPILLING, "Initial Spilling") \ + flags(CONSERVATIVE_COALESCING, "Conservative Coalescing") \ + flags(ITERATIVE_SPILLING, "Iterative Spilling") \ + flags(AFTER_ITERATIVE_SPILLING, "After Iterative Spilling") \ + flags(POST_ALLOCATION_COPY_REMOVAL, "Post-allocation Copy Removal") \ + flags(MERGE_MULTI_DEFS, "Merge Multiple Definitions") \ + flags(FIX_UP_SPILLS, "Fix up Spills") \ flags(REGISTER_ALLOCATION, "Register Allocation") \ flags(BLOCK_ORDERING, "Block Ordering") \ flags(PEEPHOLE, "Peephole") \ - flags(POSTALLOC_EXPAND, "Post-Allocation Expand") \ - flags(MACH_ANALYSIS, "After mach analysis") \ + flags(POSTALLOC_EXPAND, "Post-allocation Expand") \ + flags(MACH_ANALYSIS, "After Mach Analysis") \ flags(FINAL_CODE, "Final Code") \ flags(END, "End") \ flags(FAILURE, "Failure") \ diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java index 46900085b12..b0e5f2fda5c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java @@ -37,95 +37,96 @@ * are treated as a separated compile phase as well. */ public enum CompilePhase { - DEFAULT("For IR node placeholder strings as defined in class IRNode only"), - - BEFORE_STRINGOPTS("Before StringOpts"), - AFTER_STRINGOPTS("After StringOpts"), - BEFORE_REMOVEUSELESS("Before RemoveUseless"), - AFTER_PARSING("After Parsing"), - BEFORE_ITER_GVN("Before Iter GVN"), - ITER_GVN1("Iter GVN 1"), - AFTER_ITER_GVN_STEP("After Iter GVN Step"), - AFTER_ITER_GVN("After Iter GVN"), - INCREMENTAL_INLINE_STEP("Incremental Inline Step"), - INCREMENTAL_INLINE_CLEANUP("Incremental Inline Cleanup"), - INCREMENTAL_INLINE("Incremental Inline"), - INCREMENTAL_BOXING_INLINE("Incremental Boxing Inline"), - EXPAND_VUNBOX("Expand VectorUnbox"), - SCALARIZE_VBOX("Scalarize VectorBox"), - INLINE_VECTOR_REBOX("Inline Vector Rebox Calls"), - EXPAND_VBOX("Expand VectorBox"), - ELIMINATE_VBOX_ALLOC("Eliminate VectorBoxAllocate"), - ITER_GVN_BEFORE_EA("Iter GVN before EA"), - ITER_GVN_AFTER_VECTOR("Iter GVN after vector box elimination"), - BEFORE_LOOP_OPTS("Before Loop Optimizations"), - BEFORE_BEAUTIFY_LOOPS("Before beautify loops"), - AFTER_BEAUTIFY_LOOPS("After beautify loops"), - BEFORE_LOOP_UNROLLING("Before Loop Unrolling"), - AFTER_LOOP_UNROLLING("After Loop Unrolling"), - BEFORE_SPLIT_IF("Before Split-If"), - AFTER_SPLIT_IF("After Split-If"), - BEFORE_LOOP_PREDICATION_IC("Before Loop Predication IC"), - AFTER_LOOP_PREDICATION_IC("After Loop Predication IC"), - BEFORE_LOOP_PREDICATION_RC("Before Loop Predication RC"), - AFTER_LOOP_PREDICATION_RC("After Loop Predication RC"), - BEFORE_PARTIAL_PEELING("Before Partial Peeling"), - AFTER_PARTIAL_PEELING("After Partial Peeling"), - BEFORE_LOOP_PEELING("Before Loop Peeling"), - AFTER_LOOP_PEELING("After Loop Peeling"), - BEFORE_LOOP_UNSWITCHING("Before Loop Unswitching"), - AFTER_LOOP_UNSWITCHING("After Loop Unswitching"), - BEFORE_RANGE_CHECK_ELIMINATION("Before Range Check Elimination"), - AFTER_RANGE_CHECK_ELIMINATION("After Range Check Elimination"), - BEFORE_PRE_MAIN_POST("Before Pre/Main/Post Loops"), - AFTER_PRE_MAIN_POST("After Pre/Main/Post Loops"), - SUPERWORD1_BEFORE_SCHEDULE("Superword 1, Before Schedule"), - SUPERWORD2_BEFORE_OUTPUT("Superword 2, Before Output"), - SUPERWORD3_AFTER_OUTPUT("Superword 3, After Output"), + DEFAULT( "For IR node placeholder strings as defined in class IRNode only"), + + BEFORE_STRINGOPTS( "Before StringOpts"), + AFTER_STRINGOPTS( "After StringOpts"), + BEFORE_REMOVEUSELESS( "Before RemoveUseless"), + AFTER_PARSING( "After Parsing"), + BEFORE_ITER_GVN( "Before Iter GVN"), + ITER_GVN1( "Iter GVN 1"), + AFTER_ITER_GVN_STEP( "After Iter GVN Step"), + AFTER_ITER_GVN( "After Iter GVN"), + INCREMENTAL_INLINE_STEP( "Incremental Inline Step"), + INCREMENTAL_INLINE_CLEANUP( "Incremental Inline Cleanup"), + INCREMENTAL_INLINE( "Incremental Inline"), + INCREMENTAL_BOXING_INLINE( "Incremental Boxing Inline"), + EXPAND_VUNBOX( "Expand VectorUnbox"), + SCALARIZE_VBOX( "Scalarize VectorBox"), + INLINE_VECTOR_REBOX( "Inline Vector Rebox Calls"), + EXPAND_VBOX( "Expand VectorBox"), + ELIMINATE_VBOX_ALLOC( "Eliminate VectorBoxAllocate"), + ITER_GVN_BEFORE_EA( "Iter GVN before EA"), + ITER_GVN_AFTER_VECTOR( "Iter GVN after Vector Box Elimination"), + BEFORE_LOOP_OPTS( "Before Loop Optimizations"), + PHASEIDEAL_BEFORE_EA( "PhaseIdealLoop before EA"), + AFTER_EA( "After Escape Analysis"), + ITER_GVN_AFTER_EA( "Iter GVN after EA"), + BEFORE_BEAUTIFY_LOOPS( "Before Beautify Loops"), + AFTER_BEAUTIFY_LOOPS( "After Beautify Loops"), // Match on very first BEFORE_CLOOPS phase (there could be multiple phases for multiple loops in the code). - BEFORE_CLOOPS("Before CountedLoop", RegexType.IDEAL_INDEPENDENT, ActionOnRepeat.KEEP_FIRST), - AFTER_CLOOPS("After CountedLoop"), - PHASEIDEAL_BEFORE_EA("PhaseIdealLoop before EA"), - AFTER_EA("After Escape Analysis"), - ITER_GVN_AFTER_EA("Iter GVN after EA"), - ITER_GVN_AFTER_ELIMINATION("Iter GVN after eliminating allocations and locks"), - PHASEIDEALLOOP1("PhaseIdealLoop 1"), - PHASEIDEALLOOP2("PhaseIdealLoop 2"), - PHASEIDEALLOOP3("PhaseIdealLoop 3"), - BEFORE_CCP1("Before PhaseCCP 1"), - CCP1("PhaseCCP 1"), - ITER_GVN2("Iter GVN 2"), - PHASEIDEALLOOP_ITERATIONS("PhaseIdealLoop iterations"), - AFTER_LOOP_OPTS("After Loop Optimizations"), - AFTER_MERGE_STORES("After Merge Stores"), - BEFORE_MACRO_EXPANSION("Before Macro Expansion"), - AFTER_MACRO_EXPANSION_STEP("After Macro Expansion Step"), - AFTER_MACRO_EXPANSION("After Macro Expansion"), - BARRIER_EXPANSION("Barrier expand"), - OPTIMIZE_FINISHED("Optimize finished"), - PRINT_IDEAL("PrintIdeal"), - BEFORE_MATCHING("Before matching"), - MATCHING("After matching", RegexType.MACH), - GLOBAL_CODE_MOTION("Global code motion", RegexType.MACH), - INITIAL_LIVENESS("Initial liveness", RegexType.MACH), - LIVE_RANGE_STRETCHING("Live range stretching", RegexType.MACH), - AGGRESSIVE_COALESCING("Aggressive coalescing", RegexType.MACH), - INITIAL_SPILLING("Initial spilling", RegexType.MACH), - CONSERVATIVE_COALESCING("Conservative coalescing", RegexType.MACH, ActionOnRepeat.KEEP_FIRST), - ITERATIVE_SPILLING("Iterative spilling", RegexType.MACH, ActionOnRepeat.KEEP_FIRST), - AFTER_ITERATIVE_SPILLING("After iterative spilling", RegexType.MACH), - POST_ALLOCATION_COPY_REMOVAL("Post-allocation copy removal", RegexType.MACH), - MERGE_MULTI_DEFS("Merge multiple definitions", RegexType.MACH), - FIX_UP_SPILLS("Fix up spills", RegexType.MACH), - REGISTER_ALLOCATION("Register Allocation", RegexType.MACH), - BLOCK_ORDERING("Block Ordering", RegexType.MACH), - PEEPHOLE("Peephole", RegexType.MACH), - POSTALLOC_EXPAND("Post-Allocation Expand", RegexType.MACH), - MACH_ANALYSIS("After mach analysis", RegexType.MACH), - FINAL_CODE("Final Code", RegexType.MACH), - END("End"), - - PRINT_OPTO_ASSEMBLY("PrintOptoAssembly", RegexType.OPTO_ASSEMBLY), + BEFORE_CLOOPS( "Before CountedLoop", RegexType.IDEAL_INDEPENDENT, ActionOnRepeat.KEEP_FIRST), + AFTER_CLOOPS( "After CountedLoop"), + BEFORE_LOOP_UNROLLING( "Before Loop Unrolling"), + AFTER_LOOP_UNROLLING( "After Loop Unrolling"), + BEFORE_SPLIT_IF( "Before Split-If"), + AFTER_SPLIT_IF( "After Split-If"), + BEFORE_LOOP_PREDICATION_IC( "Before Loop Predication IC"), + AFTER_LOOP_PREDICATION_IC( "After Loop Predication IC"), + BEFORE_LOOP_PREDICATION_RC( "Before Loop Predication RC"), + AFTER_LOOP_PREDICATION_RC( "After Loop Predication RC"), + BEFORE_PARTIAL_PEELING( "Before Partial Peeling"), + AFTER_PARTIAL_PEELING( "After Partial Peeling"), + BEFORE_LOOP_PEELING( "Before Loop Peeling"), + AFTER_LOOP_PEELING( "After Loop Peeling"), + BEFORE_LOOP_UNSWITCHING( "Before Loop Unswitching"), + AFTER_LOOP_UNSWITCHING( "After Loop Unswitching"), + BEFORE_RANGE_CHECK_ELIMINATION( "Before Range Check Elimination"), + AFTER_RANGE_CHECK_ELIMINATION( "After Range Check Elimination"), + ITER_GVN_AFTER_ELIMINATION( "Iter GVN after Eliminating Allocations and Locks"), + BEFORE_PRE_MAIN_POST( "Before Pre/Main/Post Loops"), + AFTER_PRE_MAIN_POST( "After Pre/Main/Post Loops"), + PHASEIDEALLOOP1( "PhaseIdealLoop 1"), + PHASEIDEALLOOP2( "PhaseIdealLoop 2"), + PHASEIDEALLOOP3( "PhaseIdealLoop 3"), + AUTO_VECTORIZATION1_BEFORE_APPLY( "AutoVectorization 1, before Apply"), + AUTO_VECTORIZATION2_AFTER_REORDER( "AutoVectorization 2, after Apply Memop Reordering"), + AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT( "AutoVectorization 3, after Adjusting Pre-loop Limit"), + AUTO_VECTORIZATION4_AFTER_SPECULATIVE_RUNTIME_CHECKS("AutoVectorization 4, after Adding Speculative Runtime Checks"), + BEFORE_CCP1( "Before PhaseCCP 1"), + CCP1( "PhaseCCP 1"), + ITER_GVN2( "Iter GVN 2"), + PHASEIDEALLOOP_ITERATIONS( "PhaseIdealLoop Iterations"), + AFTER_LOOP_OPTS( "After Loop Optimizations"), + AFTER_MERGE_STORES( "After Merge Stores"), + BEFORE_MACRO_EXPANSION( "Before Macro Expansion"), + AFTER_MACRO_EXPANSION_STEP( "After Macro Expansion Step"), + AFTER_MACRO_EXPANSION( "After Macro Expansion"), + BARRIER_EXPANSION( "Barrier Expand"), + OPTIMIZE_FINISHED( "Optimize Finished"), + PRINT_IDEAL( "PrintIdeal"), + BEFORE_MATCHING( "Before Matching"), + MATCHING( "After Matching", RegexType.MACH), + GLOBAL_CODE_MOTION( "Global Code Motion", RegexType.MACH), + INITIAL_LIVENESS( "Initial Liveness", RegexType.MACH), + LIVE_RANGE_STRETCHING( "Live Range Stretching", RegexType.MACH), + AGGRESSIVE_COALESCING( "Aggressive Coalescing", RegexType.MACH), + INITIAL_SPILLING( "Initial Spilling", RegexType.MACH), + CONSERVATIVE_COALESCING( "Conservative Coalescing", RegexType.MACH, ActionOnRepeat.KEEP_FIRST), + ITERATIVE_SPILLING( "Iterative Spilling", RegexType.MACH, ActionOnRepeat.KEEP_FIRST), + AFTER_ITERATIVE_SPILLING( "After Iterative Spilling", RegexType.MACH), + POST_ALLOCATION_COPY_REMOVAL( "Post-allocation Copy Removal", RegexType.MACH), + MERGE_MULTI_DEFS( "Merge Multiple Definitions", RegexType.MACH), + FIX_UP_SPILLS( "Fix up Spills", RegexType.MACH), + REGISTER_ALLOCATION( "Register Allocation", RegexType.MACH), + BLOCK_ORDERING( "Block Ordering", RegexType.MACH), + PEEPHOLE( "Peephole", RegexType.MACH), + POSTALLOC_EXPAND( "Post-allocation Expand", RegexType.MACH), + MACH_ANALYSIS( "After Mach Analysis", RegexType.MACH), + FINAL_CODE( "Final Code", RegexType.MACH), + END( "End"), + + PRINT_OPTO_ASSEMBLY( "PrintOptoAssembly", RegexType.OPTO_ASSEMBLY), ; private static final Map PHASES_BY_PARSED_NAME = new HashMap<>(); From 57cabc6d741c14a8029aec324ba96e8ced4afcbd Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Fri, 13 Jun 2025 13:15:47 +0000 Subject: [PATCH 051/213] 8359364: java/net/URL/EarlyOrDelayedParsing test fails intermittently Reviewed-by: vyazici, syan, alanb --- .../java/net/URL/EarlyOrDelayedParsing.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/net/URL/EarlyOrDelayedParsing.java b/test/jdk/java/net/URL/EarlyOrDelayedParsing.java index 57fa76c23bb..e286631be6b 100644 --- a/test/jdk/java/net/URL/EarlyOrDelayedParsing.java +++ b/test/jdk/java/net/URL/EarlyOrDelayedParsing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,10 @@ import java.io.IOException; import java.net.ConnectException; import java.net.MalformedURLException; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.SocketAddress; +import java.net.URI; import java.net.URL; import java.net.UnknownHostException; import java.util.ArrayList; @@ -57,6 +61,19 @@ public class EarlyOrDelayedParsing { { String value = System.getProperty("jdk.net.url.delayParsing", "false"); EARLY_PARSING = !value.isEmpty() && !Boolean.parseBoolean(value); + if (!EARLY_PARSING) { + // we will open the connection in that case. + // make sure no proxy is selected + ProxySelector.setDefault(new ProxySelector() { + @Override + public List select(URI uri) { + return List.of(Proxy.NO_PROXY); + } + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { + } + }); + } } // Some characters that when included at the wrong place From 417f8ecf072daabe0f79d145ffab121e5336988f Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 13 Jun 2025 13:40:43 +0000 Subject: [PATCH 052/213] 8359224: G1: Incorrect size unit in logging of G1CollectedHeap::alloc_archive_region Reviewed-by: tschatzl, shade --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 96dbd0a6a71..c83414eac82 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -499,7 +499,7 @@ HeapWord* G1CollectedHeap::alloc_archive_region(size_t word_size, HeapWord* pref if (reserved.word_size() <= word_size) { log_info(gc, heap)("Unable to allocate regions as archive heap is too large; size requested = %zu" - " bytes, heap = %zu bytes", word_size, reserved.word_size()); + " bytes, heap = %zu bytes", word_size * HeapWordSize, reserved.byte_size()); return nullptr; } From 78b1360e7de84585d6e387ac6e0789a4d02187d5 Mon Sep 17 00:00:00 2001 From: dermster Date: Fri, 13 Jun 2025 15:57:00 +0000 Subject: [PATCH 053/213] 8359127: Amend java/nio/channels/DatagramChannel/PromiscuousIPv6.java to use @requires for OS platform selection Reviewed-by: djelinski, dfuchs --- .../DatagramChannel/PromiscuousIPv6.java | 24 ++++++------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java b/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java index b7bbba8e16b..6915ee247d1 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java +++ b/test/jdk/java/nio/channels/DatagramChannel/PromiscuousIPv6.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ * PromiscuousIPv6 * @run main PromiscuousIPv6 * @key randomness + * @requires (os.family == "linux") | (os.family == "mac") */ import java.nio.ByteBuffer; @@ -201,26 +202,15 @@ static void test(ProtocolFamily family, } } - /* - * returns true if platform allows an IPv6 socket join an IPv4 multicast group - */ - private static boolean supportedByPlatform() { - return Platform.isOSX() || Platform.isLinux(); - } - public static void main(String[] args) throws IOException { boolean hasIPV6MulticastAll; - if (!supportedByPlatform()) { - throw new SkippedException("This test should not be run on this platform"); - } else { - int major = Platform.getOsVersionMajor(); - int minor = Platform.getOsVersionMinor(); - hasIPV6MulticastAll = - Platform.isOSX() || - (Platform.isLinux() && ((major > 4) || ((major == 4 && minor >= 20)))); - } + int major = Platform.getOsVersionMajor(); + int minor = Platform.getOsVersionMinor(); + hasIPV6MulticastAll = + Platform.isOSX() || + (Platform.isLinux() && ((major > 4) || ((major == 4 && minor >= 20)))); NetworkConfiguration.printSystemConfiguration(System.out); List nifs = NetworkConfiguration.probe() From 366650a438d046f3da5b490c42e37faaf3a9abc5 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 13 Jun 2025 16:11:49 +0000 Subject: [PATCH 054/213] 8355556: JVM crash because archived method handle intrinsics are not restored Reviewed-by: adinn, vlivanov, shade --- src/hotspot/share/runtime/threads.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 8d8d4782e94..7251411a167 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -771,8 +771,8 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { #endif if (CDSConfig::is_using_aot_linked_classes()) { - AOTLinkedClassBulkLoader::finish_loading_javabase_classes(CHECK_JNI_ERR); SystemDictionary::restore_archived_method_handle_intrinsics(); + AOTLinkedClassBulkLoader::finish_loading_javabase_classes(CHECK_JNI_ERR); } // Start string deduplication thread if requested. From 12a0dd03b89cc3bf7f9d32b17eb41ff2bf687536 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Fri, 13 Jun 2025 16:20:11 +0000 Subject: [PATCH 055/213] 8358738: AOT cache created without graal jit should not be used with graal jit Reviewed-by: iklam, ccheung --- src/hotspot/share/cds/filemap.cpp | 20 +++++++++++++++++++ src/hotspot/share/cds/filemap.hpp | 1 + .../share/compiler/compilerDefinitions.hpp | 2 ++ .../compiler/compilerDefinitions.inline.hpp | 13 ++++++++++++ 4 files changed, 36 insertions(+) diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index a413aa2d8e8..59df255fcf3 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -44,6 +44,7 @@ #include "classfile/systemDictionaryShared.hpp" #include "classfile/vmClasses.hpp" #include "classfile/vmSymbols.hpp" +#include "compiler/compilerDefinitions.inline.hpp" #include "jvm.h" #include "logging/log.hpp" #include "logging/logMessage.hpp" @@ -232,6 +233,8 @@ void FileMapHeader::populate(FileMapInfo *info, size_t core_region_alignment, } else { _narrow_klass_pointer_bits = _narrow_klass_shift = -1; } + // Which JIT compier is used + _compiler_type = (u1)CompilerConfig::compiler_type(); _type_profile_level = TypeProfileLevel; _type_profile_args_limit = TypeProfileArgsLimit; _type_profile_parms_limit = TypeProfileParmsLimit; @@ -1935,6 +1938,23 @@ bool FileMapHeader::validate() { CompactStrings ? "enabled" : "disabled"); return false; } + bool jvmci_compiler_is_enabled = CompilerConfig::is_jvmci_compiler_enabled(); + CompilerType compiler_type = CompilerConfig::compiler_type(); + CompilerType archive_compiler_type = CompilerType(_compiler_type); + // JVMCI compiler does different type profiling settigns and generate + // different code. We can't use archive which was produced + // without it and reverse. + // Only allow mix when JIT compilation is disabled. + // Interpreter is used by default when dumping archive. + bool intepreter_is_used = (archive_compiler_type == CompilerType::compiler_none) || + (compiler_type == CompilerType::compiler_none); + if (!intepreter_is_used && + jvmci_compiler_is_enabled != (archive_compiler_type == CompilerType::compiler_jvmci)) { + MetaspaceShared::report_loading_error("The %s's JIT compiler setting (%s)" + " does not equal the current setting (%s).", file_type, + compilertype2name(archive_compiler_type), compilertype2name(compiler_type)); + return false; + } if (TrainingData::have_data()) { if (_type_profile_level != TypeProfileLevel) { MetaspaceShared::report_loading_error("The %s's TypeProfileLevel setting (%d)" diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index e0b33fc8245..02390874f39 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -147,6 +147,7 @@ class FileMapHeader: private CDSFileMapHeaderBase { size_t _ro_ptrmap_start_pos; // The first bit in the ptrmap corresponds to this position in the ro region // The following are parameters that affect MethodData layout. + u1 _compiler_type; uint _type_profile_level; int _type_profile_args_limit; int _type_profile_parms_limit; diff --git a/src/hotspot/share/compiler/compilerDefinitions.hpp b/src/hotspot/share/compiler/compilerDefinitions.hpp index bacc1f73f97..1c8c65b2a53 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.hpp @@ -149,6 +149,8 @@ class CompilerConfig : public AllStatic { inline static bool is_c2_or_jvmci_compiler_only(); inline static bool is_c2_or_jvmci_compiler_enabled(); + inline static CompilerType compiler_type(); + private: static bool is_compilation_mode_selected(); static void set_compilation_policy_flags(); diff --git a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp index fe17b77535f..21bf80549f4 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp @@ -131,4 +131,17 @@ inline bool CompilerConfig::is_c2_or_jvmci_compiler_enabled() { return is_c2_enabled() || is_jvmci_compiler_enabled(); } +// Return type of most optimizing compiler which is used +inline CompilerType CompilerConfig::compiler_type() { + CompilerType compiler_type = CompilerType::compiler_none; // Interpreter only + if (CompilerConfig::is_c2_enabled()) { + compiler_type = CompilerType::compiler_c2; + } else if (CompilerConfig::is_jvmci_compiler_enabled()) { + compiler_type = CompilerType::compiler_jvmci; + } else if (CompilerConfig::is_c1_enabled()) { + compiler_type = CompilerType::compiler_c1; + } + return compiler_type; +} + #endif // SHARE_COMPILER_COMPILERDEFINITIONS_INLINE_HPP From ee35f6384fdd0783a7ae62508e837a66683cdd3c Mon Sep 17 00:00:00 2001 From: Andrew Dinn Date: Fri, 13 Jun 2025 16:52:40 +0000 Subject: [PATCH 056/213] 8359373: Split stubgen initial blob into pre and post-universe blobs Reviewed-by: kvn --- .../cpu/aarch64/stubDeclarations_aarch64.hpp | 7 ++++ .../cpu/aarch64/stubGenerator_aarch64.cpp | 7 ++++ src/hotspot/cpu/arm/stubDeclarations_arm.hpp | 7 ++++ src/hotspot/cpu/arm/stubGenerator_arm.cpp | 7 ++++ src/hotspot/cpu/ppc/stubDeclarations_ppc.hpp | 7 ++++ src/hotspot/cpu/ppc/stubGenerator_ppc.cpp | 7 ++++ .../cpu/riscv/stubDeclarations_riscv.hpp | 7 ++++ src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 7 ++++ .../cpu/s390/stubDeclarations_s390.hpp | 7 ++++ src/hotspot/cpu/s390/stubGenerator_s390.cpp | 7 ++++ src/hotspot/cpu/x86/stubDeclarations_x86.hpp | 7 ++++ src/hotspot/cpu/x86/stubGenerator_x86_64.cpp | 11 +++-- src/hotspot/cpu/x86/stubGenerator_x86_64.hpp | 1 + .../cpu/zero/stubDeclarations_zero.hpp | 7 ++++ src/hotspot/cpu/zero/stubGenerator_zero.cpp | 8 +++- src/hotspot/share/runtime/init.cpp | 3 ++ .../share/runtime/stubDeclarations.hpp | 40 +++++++++++++++---- src/hotspot/share/runtime/stubRoutines.cpp | 8 ++++ 18 files changed, 143 insertions(+), 12 deletions(-) diff --git a/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp b/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp index e0ca01ba6ce..695534604b8 100644 --- a/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubDeclarations_aarch64.hpp @@ -26,6 +26,13 @@ #ifndef CPU_AARCH64_STUBDECLARATIONS_HPP #define CPU_AARCH64_STUBDECLARATIONS_HPP +#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \ + do_arch_blob, \ + do_arch_entry, \ + do_arch_entry_init) \ + do_arch_blob(preuniverse, 0) \ + + #define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index a0d1e22ff96..8241e94c108 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -11653,6 +11653,10 @@ class StubGenerator: public StubCodeGenerator { }; // Initialization + void generate_preuniverse_stubs() { + // preuniverse stubs are not needed for aarch64 + } + void generate_initial_stubs() { // Generate initial stubs and initializes the entry points @@ -11898,6 +11902,9 @@ class StubGenerator: public StubCodeGenerator { public: StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { + case preuniverse_id: + generate_preuniverse_stubs(); + break; case initial_id: generate_initial_stubs(); break; diff --git a/src/hotspot/cpu/arm/stubDeclarations_arm.hpp b/src/hotspot/cpu/arm/stubDeclarations_arm.hpp index 35df4b924d2..93ab16791b5 100644 --- a/src/hotspot/cpu/arm/stubDeclarations_arm.hpp +++ b/src/hotspot/cpu/arm/stubDeclarations_arm.hpp @@ -26,6 +26,13 @@ #ifndef CPU_ARM_STUBDECLARATIONS_HPP #define CPU_ARM_STUBDECLARATIONS_HPP +#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \ + do_arch_blob, \ + do_arch_entry, \ + do_arch_entry_init) \ + do_arch_blob(preuniverse, 0) \ + + #define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ diff --git a/src/hotspot/cpu/arm/stubGenerator_arm.cpp b/src/hotspot/cpu/arm/stubGenerator_arm.cpp index fc5bcb4e0e6..5f2fd2e3b6d 100644 --- a/src/hotspot/cpu/arm/stubGenerator_arm.cpp +++ b/src/hotspot/cpu/arm/stubGenerator_arm.cpp @@ -3126,6 +3126,10 @@ class StubGenerator: public StubCodeGenerator { //--------------------------------------------------------------------------- // Initialization + void generate_preuniverse_stubs() { + // preuniverse stubs are not needed for arm + } + void generate_initial_stubs() { // Generates all stubs and initializes the entry points @@ -3201,6 +3205,9 @@ class StubGenerator: public StubCodeGenerator { public: StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { + case preuniverse_id: + generate_preuniverse_stubs(); + break; case initial_id: generate_initial_stubs(); break; diff --git a/src/hotspot/cpu/ppc/stubDeclarations_ppc.hpp b/src/hotspot/cpu/ppc/stubDeclarations_ppc.hpp index 1a19f1b8cf2..be51afe42a4 100644 --- a/src/hotspot/cpu/ppc/stubDeclarations_ppc.hpp +++ b/src/hotspot/cpu/ppc/stubDeclarations_ppc.hpp @@ -26,6 +26,13 @@ #ifndef CPU_PPC_STUBDECLARATIONS_HPP #define CPU_PPC_STUBDECLARATIONS_HPP +#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \ + do_arch_blob, \ + do_arch_entry, \ + do_arch_entry_init) \ + do_arch_blob(preuniverse, 0) \ + + #define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index 2624131033c..ba4b00197fb 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -4938,6 +4938,10 @@ void generate_lookup_secondary_supers_table_stub() { } // Initialization + void generate_preuniverse_stubs() { + // preuniverse stubs are not needed for ppc + } + void generate_initial_stubs() { // Generates all stubs and initializes the entry points @@ -5067,6 +5071,9 @@ void generate_lookup_secondary_supers_table_stub() { public: StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { + case preuniverse_id: + generate_preuniverse_stubs(); + break; case initial_id: generate_initial_stubs(); break; diff --git a/src/hotspot/cpu/riscv/stubDeclarations_riscv.hpp b/src/hotspot/cpu/riscv/stubDeclarations_riscv.hpp index 4905566c233..fe7f52884fa 100644 --- a/src/hotspot/cpu/riscv/stubDeclarations_riscv.hpp +++ b/src/hotspot/cpu/riscv/stubDeclarations_riscv.hpp @@ -26,6 +26,13 @@ #ifndef CPU_RISCV_STUBDECLARATIONS_HPP #define CPU_RISCV_STUBDECLARATIONS_HPP +#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \ + do_arch_blob, \ + do_arch_entry, \ + do_arch_entry_init) \ + do_arch_blob(preuniverse, 0) \ + + #define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index c58f6bc338d..f7d13578caf 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -6660,6 +6660,10 @@ static const int64_t right_3_bits = right_n_bits(3); #undef __ // Initialization + void generate_preuniverse_stubs() { + // preuniverse stubs are not needed for riscv + } + void generate_initial_stubs() { // Generate initial stubs and initializes the entry points @@ -6815,6 +6819,9 @@ static const int64_t right_3_bits = right_n_bits(3); public: StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { + case preuniverse_id: + generate_preuniverse_stubs(); + break; case initial_id: generate_initial_stubs(); break; diff --git a/src/hotspot/cpu/s390/stubDeclarations_s390.hpp b/src/hotspot/cpu/s390/stubDeclarations_s390.hpp index f382a319c48..c3ad3cefeb9 100644 --- a/src/hotspot/cpu/s390/stubDeclarations_s390.hpp +++ b/src/hotspot/cpu/s390/stubDeclarations_s390.hpp @@ -26,6 +26,13 @@ #ifndef CPU_S390_STUBDECLARATIONS_HPP #define CPU_S390_STUBDECLARATIONS_HPP +#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \ + do_arch_blob, \ + do_arch_entry, \ + do_arch_entry_init) \ + do_arch_blob(preuniverse, 0) \ + + #define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ diff --git a/src/hotspot/cpu/s390/stubGenerator_s390.cpp b/src/hotspot/cpu/s390/stubGenerator_s390.cpp index d3f6540a3ea..d1c794002e7 100644 --- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp @@ -3283,6 +3283,10 @@ class StubGenerator: public StubCodeGenerator { return start; } + void generate_preuniverse_stubs() { + // preuniverse stubs are not needed for s390 + } + void generate_initial_stubs() { // Generates all stubs and initializes the entry points. @@ -3418,6 +3422,9 @@ class StubGenerator: public StubCodeGenerator { public: StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { + case preuniverse_id: + generate_preuniverse_stubs(); + break; case initial_id: generate_initial_stubs(); break; diff --git a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp index 2ca05bc773e..7cbe3829783 100644 --- a/src/hotspot/cpu/x86/stubDeclarations_x86.hpp +++ b/src/hotspot/cpu/x86/stubDeclarations_x86.hpp @@ -26,6 +26,13 @@ #ifndef CPU_X86_STUBDECLARATIONS_HPP #define CPU_X86_STUBDECLARATIONS_HPP +#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \ + do_arch_blob, \ + do_arch_entry, \ + do_arch_entry_init) \ + do_arch_blob(preuniverse, 500) \ + + #define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp index 1014c1c376f..e6dd880527c 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.cpp @@ -4049,6 +4049,11 @@ void StubGenerator::create_control_words() { } // Initialization +void StubGenerator::generate_preuniverse_stubs() { + // atomic calls + StubRoutines::_fence_entry = generate_orderaccess_fence(); +} + void StubGenerator::generate_initial_stubs() { // Generates all stubs and initializes the entry points @@ -4074,9 +4079,6 @@ void StubGenerator::generate_initial_stubs() { // is referenced by megamorphic call StubRoutines::_catch_exception_entry = generate_catch_exception(); - // atomic calls - StubRoutines::_fence_entry = generate_orderaccess_fence(); - // platform dependent StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp(); @@ -4344,6 +4346,9 @@ void StubGenerator::generate_compiler_stubs() { StubGenerator::StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { + case preuniverse_id: + generate_preuniverse_stubs(); + break; case initial_id: generate_initial_stubs(); break; diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp index 2f1e46f3132..032e05f4b4f 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64.hpp @@ -634,6 +634,7 @@ class StubGenerator: public StubCodeGenerator { void create_control_words(); // Initialization + void generate_preuniverse_stubs(); void generate_initial_stubs(); void generate_continuation_stubs(); void generate_compiler_stubs(); diff --git a/src/hotspot/cpu/zero/stubDeclarations_zero.hpp b/src/hotspot/cpu/zero/stubDeclarations_zero.hpp index 5808ae3bd8f..2357bbb5169 100644 --- a/src/hotspot/cpu/zero/stubDeclarations_zero.hpp +++ b/src/hotspot/cpu/zero/stubDeclarations_zero.hpp @@ -26,6 +26,13 @@ #ifndef CPU_ZERO_STUBDECLARATIONS_HPP #define CPU_ZERO_STUBDECLARATIONS_HPP +#define STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, \ + do_arch_blob, \ + do_arch_entry, \ + do_arch_entry_init) \ + do_arch_blob(preuniverse, 0) \ + + #define STUBGEN_INITIAL_BLOBS_ARCH_DO(do_stub, \ do_arch_blob, \ do_arch_entry, \ diff --git a/src/hotspot/cpu/zero/stubGenerator_zero.cpp b/src/hotspot/cpu/zero/stubGenerator_zero.cpp index 07b4e2a92af..65fe33dcba4 100644 --- a/src/hotspot/cpu/zero/stubGenerator_zero.cpp +++ b/src/hotspot/cpu/zero/stubGenerator_zero.cpp @@ -178,6 +178,10 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_oop_arraycopy; } + void generate_preuniverse_stubs() { + StubRoutines::_fence_entry = ShouldNotCallThisStub(); + } + void generate_initial_stubs() { // entry points that exist in all platforms Note: This is code // that could be shared among different platforms - however the @@ -194,7 +198,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_atomic_cmpxchg_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_cmpxchg_long_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_add_entry = ShouldNotCallThisStub(); - StubRoutines::_fence_entry = ShouldNotCallThisStub(); } void generate_continuation_stubs() { @@ -214,6 +217,9 @@ class StubGenerator: public StubCodeGenerator { public: StubGenerator(CodeBuffer* code, StubGenBlobId blob_id) : StubCodeGenerator(code, blob_id) { switch(blob_id) { + case preuniverse_id: + generate_preuniverse_stubs(); + break; case initial_id: generate_initial_stubs(); break; diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp index 22a2e302600..dbd0a355efe 100644 --- a/src/hotspot/share/runtime/init.cpp +++ b/src/hotspot/share/runtime/init.cpp @@ -68,6 +68,7 @@ void compilationPolicy_init(); void codeCache_init(); void VM_Version_init(); void icache_init2(); +void preuniverse_stubs_init(); void initial_stubs_init(); jint universe_init(); // depends on codeCache_init and initial_stubs_init @@ -129,6 +130,8 @@ jint init_globals() { codeCache_init(); VM_Version_init(); // depends on codeCache_init for emitting code icache_init2(); // depends on VM_Version for choosing the mechanism + // initialize stubs needed before we can init the universe + preuniverse_stubs_init(); // stub routines in initial blob are referenced by later generated code initial_stubs_init(); // stack overflow exception blob is referenced by the interpreter diff --git a/src/hotspot/share/runtime/stubDeclarations.hpp b/src/hotspot/share/runtime/stubDeclarations.hpp index 5dc7d293662..8c01434b73a 100644 --- a/src/hotspot/share/runtime/stubDeclarations.hpp +++ b/src/hotspot/share/runtime/stubDeclarations.hpp @@ -175,12 +175,13 @@ // Stub Generator Blobs and Stubs Overview // // StubGenerator stubs do not require their own individual blob. They -// are generated in batches into one of four distinct BufferBlobs: +// are generated in batches into one of five distinct BufferBlobs: // -// 1) Initial stubs -// 2) Continuation stubs -// 3) Compiler stubs -// 4) Final stubs +// 1) PreUniverse stubs +// 2) Initial stubs +// 3) Continuation stubs +// 4) Compiler stubs +// 5) Final stubs // // Creation of each successive BufferBlobs is staged to ensure that // specific VM subsystems required by those stubs are suitably @@ -268,6 +269,7 @@ // For example, // // enum platform_dependent_constants { +// _preuniverse_stubs_code_size = 500, // _initial_stubs_code_size = 10000, // _continuation_stubs_code_size = 2000, // . . . @@ -501,6 +503,10 @@ #include CPU_HEADER(stubDeclarations) +#ifndef STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO +#error "Arch-specific directory failed to declare required initial stubs and entries" +#endif + #ifndef STUBGEN_INITIAL_BLOBS_ARCH_DO #error "Arch-specific directory failed to declare required initial stubs and entries" #endif @@ -533,7 +539,21 @@ // stubs within the correct blob and locate entry declarations // immediately after their associated stub declaration. -#define STUBGEN_INITIAL_BLOBS_DO(do_blob, end_blob, \ +#define STUBGEN_PREUNIVERSE_BLOBS_DO(do_blob, end_blob, \ + do_stub, \ + do_entry, do_entry_init, \ + do_entry_array, \ + do_arch_blob, \ + do_arch_entry, do_arch_entry_init) \ + do_blob(preuniverse) \ + do_stub(preuniverse, fence) \ + do_entry(preuniverse, fence, fence_entry, fence_entry) \ + /* merge in stubs and entries declared in arch header */ \ + STUBGEN_PREUNIVERSE_BLOBS_ARCH_DO(do_stub, do_arch_blob, \ + do_arch_entry, do_arch_entry_init) \ + end_blob(preuniverse) \ + +#define STUBGEN_INITIAL_BLOBS_DO(do_blob, end_blob, \ do_stub, \ do_entry, do_entry_init, \ do_entry_array, \ @@ -550,8 +570,6 @@ do_stub(initial, catch_exception) \ do_entry(initial, catch_exception, catch_exception_entry, \ catch_exception_entry) \ - do_stub(initial, fence) \ - do_entry(initial, fence, fence_entry, fence_entry) \ do_stub(initial, atomic_add) \ do_entry(initial, atomic_add, atomic_add_entry, atomic_add_entry) \ do_stub(initial, atomic_xchg) \ @@ -1012,6 +1030,12 @@ do_entry_array, \ do_arch_blob, \ do_arch_entry, do_arch_entry_init) \ + STUBGEN_PREUNIVERSE_BLOBS_DO(do_blob, end_blob, \ + do_stub, \ + do_entry, do_entry_init, \ + do_entry_array, \ + do_arch_blob, \ + do_arch_entry, do_arch_entry_init) \ STUBGEN_INITIAL_BLOBS_DO(do_blob, end_blob, \ do_stub, \ do_entry, do_entry_init, \ diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index 358434938f2..163ab4bfb6a 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -220,6 +220,14 @@ static BufferBlob* initialize_stubs(StubGenBlobId blob_id, const char* buffer_name, const char* assert_msg) { ResourceMark rm; + if (code_size == 0) { + LogTarget(Info, stubs) lt; + if (lt.is_enabled()) { + LogStream ls(lt); + ls.print_cr("%s\t not generated", buffer_name); + return nullptr; + } + } TraceTime timer(timer_msg, TRACETIME_LOG(Info, startuptime)); // Add extra space for large CodeEntryAlignment int size = code_size + CodeEntryAlignment * max_aligned_stubs; From b3f56086c99023a30b91f90c2acbed51b3b17ec0 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Fri, 13 Jun 2025 17:15:41 +0000 Subject: [PATCH 057/213] 8358094: Test vmTestbase/nsk/jvmti/AttachOnDemand/attach045/TestDescription.java still times out after JDK-8357282 Reviewed-by: sspitsyn, cjplummer, lmesnik --- test/hotspot/jtreg/ProblemList.txt | 1 - .../AttachOnDemand/attach045/attach045Agent00.cpp | 9 +++++---- .../AttachOnDemand/attach045/attach045Agent01.cpp | 10 +++++----- .../AttachOnDemand/attach045/attach045Agent02.cpp | 10 +++++----- .../AttachOnDemand/attach045/attach045Agent03.cpp | 10 +++++----- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index f0e50e58b2b..182b428fecd 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -168,7 +168,6 @@ vmTestbase/metaspace/gc/firstGC_50m/TestDescription.java 8208250 generic-all vmTestbase/metaspace/gc/firstGC_99m/TestDescription.java 8208250 generic-all vmTestbase/metaspace/gc/firstGC_default/TestDescription.java 8208250 generic-all -vmTestbase/nsk/jvmti/AttachOnDemand/attach045/TestDescription.java 8358094 generic-all vmTestbase/nsk/jvmti/scenarios/capability/CM03/cm03t001/TestDescription.java 8073470 linux-all vmTestbase/nsk/jvmti/InterruptThread/intrpthrd003/TestDescription.java 8288911 macosx-all diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent00.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent00.cpp index 5a486492799..06ea3a007d1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent00.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent00.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,6 +51,7 @@ void JNICALL classLoadHandler( jclass klass) { char className[MAX_STRING_LENGTH]; int success = 1; + bool finish = false; if (!nsk_jvmti_aod_getClassName(jvmti, klass, className)) { nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_CLASS_LOAD, 0, jvmti, jni); @@ -65,7 +66,7 @@ void JNICALL classLoadHandler( if (eventsCounter == EXPECTED_EVENTS_NUMBER) { NSK_DISPLAY2("%s: all expected events were received (eventsCounter: %d)\n", agentName, eventsCounter); - nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_CLASS_LOAD, success, jvmti, jni); + finish = true; } if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(eventsCounterMonitor))) { @@ -75,8 +76,8 @@ void JNICALL classLoadHandler( success = 0; } - if (!success) { - nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_CLASS_LOAD, 0, jvmti, jni); + if (finish || !success) { + nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_CLASS_LOAD, success, jvmti, jni); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent01.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent01.cpp index 8843c19d338..017d58680e5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent01.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent01.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,7 @@ void JNICALL classPrepareHandler( jthread thread, jclass klass) { int success = 1; + bool finish = false; char className[MAX_STRING_LENGTH]; jint loadedClassesCount; jclass *loadedClasses; @@ -75,8 +76,7 @@ void JNICALL classPrepareHandler( if (eventsCounter == EXPECTED_EVENTS_NUMBER) { NSK_DISPLAY2("%s: all expected events were received (eventsCounter: %d)\n", agentName, eventsCounter); - - nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_CLASS_PREPARE, success, jvmti, jni); + finish = true; } if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(eventsCounterMonitor))) { @@ -86,8 +86,8 @@ void JNICALL classPrepareHandler( success = 0; } - if (!success) { - nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_CLASS_PREPARE, 0, jvmti, jni); + if (finish || !success) { + nsk_jvmti_aod_disableEventAndFinish(agentName, JVMTI_EVENT_CLASS_PREPARE, success, jvmti, jni); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent02.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent02.cpp index f0ce8965cda..ab0d489b770 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent02.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent02.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,6 +54,7 @@ void eventHandler(jvmtiEnv *jvmti, int threadStartEvent) { char threadName[MAX_STRING_LENGTH]; int success = 1; + bool finish = false; jint threadsCount = 0; jthread * threads; @@ -81,8 +82,7 @@ void eventHandler(jvmtiEnv *jvmti, if (eventsCounter == EXPECTED_EVENTS_NUMBER) { NSK_DISPLAY2("%s: all expected events were received (eventsCounter: %d)\n", agentName, eventsCounter); - - nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, success, jvmti, jni); + finish = true; } if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(eventsCounterMonitor))) { @@ -92,8 +92,8 @@ void eventHandler(jvmtiEnv *jvmti, success = 0; } - if (!success) { - nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, 0, jvmti, jni); + if (finish || !success) { + nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, success, jvmti, jni); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent03.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent03.cpp index 3834e868a7b..99a657a85b0 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent03.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/AttachOnDemand/attach045/attach045Agent03.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,7 @@ VMObjectAllocHandler(jvmtiEnv *jvmti, char threadName[MAX_STRING_LENGTH]; char className[MAX_STRING_LENGTH]; int success = 1; + bool finish = false; if (!nsk_jvmti_aod_getClassName(jvmti, object_klass, className)) { nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, 0, jvmti, jni); @@ -84,8 +85,7 @@ VMObjectAllocHandler(jvmtiEnv *jvmti, if (eventsCounter == EXPECTED_EVENTS_NUMBER) { NSK_DISPLAY2("%s: all expected events were received (eventsCounter: %d)\n", agentName, eventsCounter); - - nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, success, jvmti, jni); + finish = true; } if (!NSK_JVMTI_VERIFY(jvmti->RawMonitorExit(eventsCounterMonitor))) { @@ -95,8 +95,8 @@ VMObjectAllocHandler(jvmtiEnv *jvmti, success = 0; } - if (!success) { - nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, 0, jvmti, jni); + if (finish || !success) { + nsk_jvmti_aod_disableEventsAndFinish(agentName, testEvents, testEventsNumber, success, jvmti, jni); } } From 0e725c6fb1f324b0fd17d206806b4104dc7ba767 Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Fri, 13 Jun 2025 21:42:17 +0000 Subject: [PATCH 058/213] 8354447: Missing test for retroactive @SuppressWarnings("dangling-doc-comments") behavior Reviewed-by: darcy --- .../danglingDocComments/DanglingDocCommentsClass.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass.java b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass.java index 3f6553d191f..9d2adbc656f 100644 --- a/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass.java +++ b/test/langtools/tools/javac/danglingDocComments/DanglingDocCommentsClass.java @@ -45,4 +45,13 @@ public void m4b() { } /** Good comment. */ int i = 0; } -} \ No newline at end of file + + /** Dangling comment X */ + + /** + * The {@code @SuppressWarnings} annotation below retroactively + * silences the warning about "Dangling comment X". + */ + @SuppressWarnings("dangling-doc-comments") + public void m5() { } +} From 26848a7d6ce4c573b679a690fd36e6d7082243f6 Mon Sep 17 00:00:00 2001 From: Raffaello Giulietti Date: Sat, 14 Jun 2025 08:15:12 +0000 Subject: [PATCH 059/213] 8358804: Improve the API Note of BigDecimal.valueOf(double) Reviewed-by: bpb, darcy, iris --- src/java.base/share/classes/java/math/BigDecimal.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index 6fdd3e7fcc2..534f840174c 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -1372,10 +1372,15 @@ static BigDecimal zeroValueOf(int scale) { * by the {@link Double#toString(double)} method. * * @apiNote This is generally the preferred way to convert a - * {@code double} (or {@code float}) into a {@code BigDecimal}, as + * {@code double} into a {@code BigDecimal}, as * the value returned is equal to that resulting from constructing * a {@code BigDecimal} from the result of using {@link * Double#toString(double)}. + *

    + * While a {@code float} argument {@code v} can be passed to this method, + * the result often contains many more trailing digits than the precision + * of a {@code float}. + * Consider using {@code new BigDecimal(Float.toString(v))} instead. * * @param val {@code double} to convert to a {@code BigDecimal}. * @return a {@code BigDecimal} whose value is equal to or approximately From 1a01839f8c0522a90710e101cce6ecc479a77529 Mon Sep 17 00:00:00 2001 From: Anjian Wen Date: Mon, 16 Jun 2025 03:32:40 +0000 Subject: [PATCH 060/213] 8359105: RISC-V: No need for acquire fence in safepoint poll during JNI calls Reviewed-by: rehn, fyang, fjiang --- src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 2 +- src/hotspot/cpu/riscv/downcallLinker_riscv.cpp | 2 +- src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 2 +- src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 5 +---- src/hotspot/cpu/riscv/macroAssembler_riscv.hpp | 2 +- src/hotspot/cpu/riscv/riscv.ad | 2 +- src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 10 +--------- .../cpu/riscv/templateInterpreterGenerator_riscv.cpp | 12 ++---------- 8 files changed, 9 insertions(+), 28 deletions(-) diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index 08d35c2831a..c7587765da0 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -401,7 +401,7 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { code_stub->set_safepoint_offset(__ offset()); __ relocate(relocInfo::poll_return_type); - __ safepoint_poll(*code_stub->entry(), true /* at_return */, false /* acquire */, true /* in_nmethod */); + __ safepoint_poll(*code_stub->entry(), true /* at_return */, true /* in_nmethod */); __ ret(); } diff --git a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp index d1278c419a0..cc685645ec5 100644 --- a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp +++ b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp @@ -287,7 +287,7 @@ void DowncallLinker::StubGenerator::generate() { __ membar(MacroAssembler::AnyAny); } - __ safepoint_poll(L_safepoint_poll_slow_path, true /* at_return */, true /* acquire */, false /* in_nmethod */); + __ safepoint_poll(L_safepoint_poll_slow_path, true /* at_return */, false /* in_nmethod */); __ lwu(t0, Address(xthread, JavaThread::suspend_flags_offset())); __ bnez(t0, L_safepoint_poll_slow_path); diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp index fae34a9c770..b909a884dc9 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -645,7 +645,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state, // the stack, will call InterpreterRuntime::at_unwind. Label slow_path; Label fast_path; - safepoint_poll(slow_path, true /* at_return */, false /* acquire */, false /* in_nmethod */); + safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); j(fast_path); bind(slow_path); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index c755d9ae23d..7c5b2cdbf1d 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -3739,11 +3739,8 @@ void MacroAssembler::check_klass_subtype(Register sub_klass, bind(L_failure); } -void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod, Register tmp_reg) { +void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod, Register tmp_reg) { ld(tmp_reg, Address(xthread, JavaThread::polling_word_offset())); - if (acquire) { - membar(MacroAssembler::LoadLoad | MacroAssembler::LoadStore); - } if (at_return) { bgtu(in_nmethod ? sp : fp, tmp_reg, slow_path, /* is_far */ true); } else { diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 7fa7f931044..fc60bc67b4e 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -44,7 +44,7 @@ class MacroAssembler: public Assembler { MacroAssembler(CodeBuffer* code) : Assembler(code) {} - void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod, Register tmp_reg = t0); + void safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod, Register tmp_reg = t0); // Alignment int align(int modulus, int extra_offset = 0); diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 0d44acc803f..c2f44986658 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1493,7 +1493,7 @@ void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); - __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); + __ safepoint_poll(*code_stub, true /* at_return */, true /* in_nmethod */); } } diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 391be81c1ae..216323c55fc 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -1777,15 +1777,7 @@ 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 */); + __ safepoint_poll(safepoint_in_progress, true /* at_return */, false /* in_nmethod */); __ lwu(t0, Address(xthread, JavaThread::suspend_flags_offset())); __ bnez(t0, safepoint_in_progress); __ bind(safepoint_in_progress_done); diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index b8de3547c83..21164107053 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -1229,15 +1229,7 @@ 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 */); + __ safepoint_poll(L, true /* at_return */, false /* in_nmethod */); __ lwu(t1, Address(xthread, JavaThread::suspend_flags_offset())); __ beqz(t1, Continue); __ bind(L); @@ -1388,7 +1380,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { Label slow_path; Label fast_path; - __ safepoint_poll(slow_path, true /* at_return */, false /* acquire */, false /* in_nmethod */); + __ safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); __ j(fast_path); __ bind(slow_path); From 6fe9143bbbe269af62d2084834fc0c9afc51b5f3 Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Mon, 16 Jun 2025 05:27:52 +0000 Subject: [PATCH 061/213] 8358532: JFileChooser in GTK L&F still displays HTML filename Reviewed-by: aivanov, dnguyen, kizune --- .../com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java | 6 ++++++ test/jdk/javax/swing/JFileChooser/HTMLFileName.java | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java index 19d77115025..4f18dc84f4a 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java @@ -1120,6 +1120,9 @@ public Component getListCellRendererComponent(JList list, Object value, int i if (showFileIcons) { setIcon(getFileChooser().getIcon((File)value)); } + + putClientProperty("html.disable", getFileChooser().getClientProperty("html.disable")); + return this; } } @@ -1137,6 +1140,9 @@ public Component getListCellRendererComponent(JList list, Object value, int i } else { setText(getFileChooser().getName((File)value) + "/"); } + + putClientProperty("html.disable", getFileChooser().getClientProperty("html.disable")); + return this; } } diff --git a/test/jdk/javax/swing/JFileChooser/HTMLFileName.java b/test/jdk/javax/swing/JFileChooser/HTMLFileName.java index 8783c388985..45d9cb4c449 100644 --- a/test/jdk/javax/swing/JFileChooser/HTMLFileName.java +++ b/test/jdk/javax/swing/JFileChooser/HTMLFileName.java @@ -41,7 +41,7 @@ /* * @test id=system - * @bug 8139228 + * @bug 8139228 8358532 * @summary JFileChooser should not render Directory names in HTML format * @library /java/awt/regtesthelpers * @build PassFailJFrame From 534a8605e5f4d771be69426687b2188d5353c91e Mon Sep 17 00:00:00 2001 From: Damon Fenacci Date: Mon, 16 Jun 2025 06:11:08 +0000 Subject: [PATCH 062/213] 8358129: compiler/startup/StartupOutput.java runs into out of memory on Windows after JDK-8347406 Reviewed-by: thartmann, epeter --- test/hotspot/jtreg/ProblemList.txt | 2 -- test/hotspot/jtreg/compiler/startup/StartupOutput.java | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 182b428fecd..ac51090aaa8 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -79,8 +79,6 @@ compiler/ciReplay/TestIncrementalInlining.java 8349191 generic-all compiler/c2/TestVerifyConstraintCasts.java 8355574 generic-all -compiler/startup/StartupOutput.java 8358129 windows-all - ############################################################################# # :hotspot_gc diff --git a/test/hotspot/jtreg/compiler/startup/StartupOutput.java b/test/hotspot/jtreg/compiler/startup/StartupOutput.java index 883f1a08030..22f2887a266 100644 --- a/test/hotspot/jtreg/compiler/startup/StartupOutput.java +++ b/test/hotspot/jtreg/compiler/startup/StartupOutput.java @@ -60,21 +60,17 @@ public static void main(String[] args) throws Exception { throw new Exception("VM crashed with exit code " + exitCode); } - Process[] pr = new Process[200]; for (int i = 0; i < 200; i++) { int initialCodeCacheSizeInKb = 800 + rand.nextInt(400); int reservedCodeCacheSizeInKb = initialCodeCacheSizeInKb + rand.nextInt(200); pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:InitialCodeCacheSize=" + initialCodeCacheSizeInKb + "K", "-XX:ReservedCodeCacheSize=" + reservedCodeCacheSizeInKb + "k", "-version"); - pr[i] = pb.start(); - } - for (int i = 0; i < 200; i++) { - out = new OutputAnalyzer(pr[i]); - // The VM should not crash but will probably fail with a "CodeCache is full. Compiler has been disabled." message - out.stdoutShouldNotContain("# A fatal error"); + out = new OutputAnalyzer(pb.start()); exitCode = out.getExitValue(); if (exitCode != 1 && exitCode != 0) { throw new Exception("VM crashed with exit code " + exitCode); } + // The VM should not crash but will probably fail with a "CodeCache is full. Compiler has been disabled." message + out.stdoutShouldNotContain("# A fatal error"); } } } From eacfcd86d38f4acf0165275a42d246ba6c5fae56 Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Mon, 16 Jun 2025 07:27:05 +0000 Subject: [PATCH 063/213] 8357995: Use "stdin.encoding" for reading System.in with InputStreamReader/Scanner [core] Reviewed-by: naoto, cjplummer --- .../sun/security/tools/keytool/Main.java | 23 ++-- .../security/util/ConsoleCallbackHandler.java | 8 +- .../com/sun/tools/script/shell/Main.java | 12 +- .../javax/script/SimpleScriptContext.java | 10 +- .../security/krb5/internal/tools/Ktab.java | 16 ++- .../com/sun/tools/example/debug/tty/TTY.java | 7 +- .../jdk/com/sun/jdi/MultiBreakpointsTest.java | 104 ++++++++---------- .../security/sasl/ClientCallbackHandler.java | 4 +- .../sasl/digest/ClientCallbackHandler.java | 4 +- test/jdk/java/lang/ProcessBuilder/Basic.java | 2 +- .../jdk/java/nio/charset/spi/CharsetTest.java | 9 +- 11 files changed, 102 insertions(+), 97 deletions(-) diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java index 89cad63dc65..6bea35a996f 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -26,6 +26,7 @@ package sun.security.tools.keytool; import java.io.*; +import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.security.*; @@ -1473,7 +1474,7 @@ private void doGenCert(String alias, String sigAlgName, InputStream in, PrintStr info.setVersion(new CertificateVersion(CertificateVersion.V3)); info.setIssuer(issuer); - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + BufferedReader reader = stdinAwareReader(in); boolean canRead = false; StringBuilder sb = new StringBuilder(); while (true) { @@ -2828,7 +2829,7 @@ private void printCRL(CRL crl, PrintStream out) private void doPrintCertReq(InputStream in, PrintStream out) throws Exception { - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + BufferedReader reader = stdinAwareReader(in); StringBuilder sb = new StringBuilder(); boolean started = false; while (true) { @@ -3533,8 +3534,7 @@ private String getAlias(String prompt) throws Exception { } else { System.err.print(rb.getString("Enter.alias.name.")); } - return (new BufferedReader(new InputStreamReader( - System.in))).readLine(); + return stdinAwareReader(System.in).readLine(); } /** @@ -3544,8 +3544,14 @@ private String getAlias(String prompt) throws Exception { */ private String inputStringFromStdin(String prompt) throws Exception { System.err.print(prompt); - return (new BufferedReader(new InputStreamReader( - System.in))).readLine(); + return stdinAwareReader(System.in).readLine(); + } + + private static BufferedReader stdinAwareReader(InputStream in) { + InputStreamReader reader = in == System.in + ? new InputStreamReader(in, Charset.forName(System.getProperty("stdin.encoding"), Charset.defaultCharset())) + : new InputStreamReader(in); + return new BufferedReader(reader); } /** @@ -3732,7 +3738,7 @@ private static void printExtensions(String title, CertificateExtensions exts, Pr */ private X500Name getX500Name() throws IOException { BufferedReader in; - in = new BufferedReader(new InputStreamReader(System.in)); + in = stdinAwareReader(System.in); String commonName = "Unknown"; String organizationalUnit = "Unknown"; String organization = "Unknown"; @@ -4238,8 +4244,7 @@ private String getYesNoReply(String prompt) } System.err.print(prompt); System.err.flush(); - reply = (new BufferedReader(new InputStreamReader - (System.in))).readLine(); + reply = stdinAwareReader(System.in).readLine(); if (reply == null || collator.compare(reply, "") == 0 || collator.compare(reply, rb.getString("n")) == 0 || diff --git a/src/java.base/share/classes/sun/security/util/ConsoleCallbackHandler.java b/src/java.base/share/classes/sun/security/util/ConsoleCallbackHandler.java index 83ac503b460..66140824bec 100644 --- a/src/java.base/share/classes/sun/security/util/ConsoleCallbackHandler.java +++ b/src/java.base/share/classes/sun/security/util/ConsoleCallbackHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; +import java.nio.charset.Charset; /** * A {@code CallbackHandler} that prompts and reads from the command line @@ -130,8 +131,9 @@ public void handle(Callback[] callbacks) /* Reads a line of input */ private String readLine() throws IOException { - String result = new BufferedReader - (new InputStreamReader(System.in)).readLine(); + Charset charset = Charset.forName(System.getProperty("stdin.encoding"), Charset.defaultCharset()); + InputStreamReader reader = new InputStreamReader(System.in, charset); + String result = new BufferedReader(reader).readLine(); if (result == null) { throw new IOException("Cannot read from System.in"); } diff --git a/src/java.scripting/share/classes/com/sun/tools/script/shell/Main.java b/src/java.scripting/share/classes/com/sun/tools/script/shell/Main.java index f1ac21bbfbb..96fd6d010ac 100644 --- a/src/java.scripting/share/classes/com/sun/tools/script/shell/Main.java +++ b/src/java.scripting/share/classes/com/sun/tools/script/shell/Main.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.io.*; import java.net.*; +import java.nio.charset.Charset; import java.text.*; import java.util.*; import javax.script.*; @@ -255,8 +256,8 @@ private static void listScriptEngines() { private static void processSource(ScriptEngine se, String filename, String encoding) { if (filename.equals("-")) { - BufferedReader in = new BufferedReader - (new InputStreamReader(getIn())); + Charset charset = Charset.forName(System.getProperty("stdin.encoding"), Charset.defaultCharset()); + BufferedReader in = new BufferedReader(new InputStreamReader(System.in, charset)); boolean hitEOF = false; String prompt = getPrompt(se); se.put(ScriptEngine.FILENAME, ""); @@ -402,11 +403,6 @@ private static String getMessage(String key, Object[] params) { return MessageFormat.format(msgRes.getString(key), params); } - // input stream from where we will read - private static InputStream getIn() { - return System.in; - } - // stream to print error messages private static PrintStream getError() { return System.err; diff --git a/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java b/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java index 5fcb0209107..89f5978601f 100644 --- a/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java +++ b/src/java.scripting/share/classes/javax/script/SimpleScriptContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package javax.script; +import java.nio.charset.Charset; import java.util.*; import java.io.*; @@ -86,13 +87,18 @@ public class SimpleScriptContext implements ScriptContext { * Create a {@code SimpleScriptContext}. */ public SimpleScriptContext() { - this(new InputStreamReader(System.in), + this(stdinReader(), new PrintWriter(System.out , true), new PrintWriter(System.err, true)); engineScope = new SimpleBindings(); globalScope = null; } + private static InputStreamReader stdinReader() { + Charset charset = Charset.forName(System.getProperty("stdin.encoding"), Charset.defaultCharset()); + return new InputStreamReader(System.in, charset); + } + /** * Package-private constructor to avoid needless creation of reader and writers. * It is the caller's responsibility to initialize the engine scope. diff --git a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java index 21002f3369a..ffe2e3196c1 100644 --- a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java +++ b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Ktab.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,8 @@ import java.io.IOException; import java.io.BufferedReader; import java.io.InputStreamReader; +import java.io.Reader; +import java.nio.charset.Charset; import java.text.DateFormat; import java.util.Arrays; import java.util.Date; @@ -304,8 +306,7 @@ void addEntry() { } if (password == null) { try { - BufferedReader cis = - new BufferedReader(new InputStreamReader(System.in)); + BufferedReader cis = stdinReader(); System.out.print("Password for " + pname.toString() + ":"); System.out.flush(); password = cis.readLine().toCharArray(); @@ -403,6 +404,12 @@ void listKt() { } } + private static BufferedReader stdinReader() { + Charset charset = Charset.forName(System.getProperty("stdin.encoding"), Charset.defaultCharset()); + Reader reader = new InputStreamReader(System.in, charset); + return new BufferedReader(reader); + } + /** * Deletes an entry from the key table. */ @@ -412,8 +419,7 @@ void deleteEntry() { pname = new PrincipalName(principal); if (!fopt) { String answer; - BufferedReader cis = - new BufferedReader(new InputStreamReader(System.in)); + BufferedReader cis = stdinReader(); System.out.print("Are you sure you want to delete "+ "service key(s) for " + pname.toString() + " (" + (etype==-1?"all etypes":("etype="+etype)) + ", " + diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java index acdd6c45f6e..94d06363dd1 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTY.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import com.sun.jdi.request.*; import com.sun.jdi.connect.*; +import java.nio.charset.Charset; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.io.*; @@ -796,8 +797,8 @@ public TTY() throws Exception { this.handler = new EventHandler(this, true, trackVthreads); } try { - BufferedReader in = - new BufferedReader(new InputStreamReader(System.in)); + Charset charset = Charset.forName(System.getProperty("stdin.encoding"), Charset.defaultCharset()); + BufferedReader in = new BufferedReader(new InputStreamReader(System.in, charset)); Thread.currentThread().setPriority(Thread.NORM_PRIORITY); diff --git a/test/jdk/com/sun/jdi/MultiBreakpointsTest.java b/test/jdk/com/sun/jdi/MultiBreakpointsTest.java index 6304aef96b9..bdbe36e7860 100644 --- a/test/jdk/com/sun/jdi/MultiBreakpointsTest.java +++ b/test/jdk/com/sun/jdi/MultiBreakpointsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,13 +50,8 @@ import com.sun.jdi.event.*; import com.sun.jdi.request.*; -import java.util.*; - /********** target program **********/ -import java.io.*; -import java.text.*; - class MultiBreakpointsTarg { MultiBreakpointsTarg(int numThreads, int numHits) { @@ -136,66 +131,57 @@ void bkpt28() {} void bkpt29() {} Thread console(final int num, final int nhits) { - final InputStreamReader isr = new InputStreamReader(System.in); - final BufferedReader br = new BufferedReader(isr); - // Create the threads // //final String threadName = "DebuggeeThread: " + num; final String threadName = "" + num; Thread thrd = DebuggeeWrapper.newThread(() -> { - synchronized( isr ) { - boolean done = false; - try { - // For each thread, run until numHits bkpts have been hit - for( int i = 0; i < nhits; i++ ) { - // This is a tendril from the original jdb test. - // It could probably be deleted. - System.out.println("Thread " + threadName + " Enter a string: "); - String s = "test" + num; - switch (num) { - case 0: bkpt0(); break; - case 1: bkpt1(); break; - case 2: bkpt2(); break; - case 3: bkpt3(); break; - case 4: bkpt4(); break; - case 5: bkpt5(); break; - case 6: bkpt6(); break; - case 7: bkpt7(); break; - case 8: bkpt8(); break; - case 9: bkpt9(); break; - case 10: bkpt10(); break; - case 11: bkpt11(); break; - case 12: bkpt12(); break; - case 13: bkpt13(); break; - case 14: bkpt14(); break; - case 15: bkpt15(); break; - case 16: bkpt16(); break; - case 17: bkpt17(); break; - case 18: bkpt18(); break; - case 19: bkpt19(); break; - case 20: bkpt20(); break; - case 21: bkpt21(); break; - case 22: bkpt22(); break; - case 23: bkpt23(); break; - case 24: bkpt24(); break; - case 25: bkpt25(); break; - case 26: bkpt26(); break; - case 27: bkpt27(); break; - case 28: bkpt28(); break; - case 29: bkpt29(); break; - } - System.out.println("Thread " + threadName + " You entered : " + s); - - if( s.compareTo( "quit" ) == 0 ) - done = true; - } - } catch(Exception e) { - System.out.println("WOOPS"); - } + try { + // For each thread, run until numHits bkpts have been hit + for( int i = 0; i < nhits; i++ ) { + // This is a tendril from the original jdb test. + // It could probably be deleted. + System.out.println("Thread " + threadName + " Enter a string: "); + String s = "test" + num; + switch (num) { + case 0: bkpt0(); break; + case 1: bkpt1(); break; + case 2: bkpt2(); break; + case 3: bkpt3(); break; + case 4: bkpt4(); break; + case 5: bkpt5(); break; + case 6: bkpt6(); break; + case 7: bkpt7(); break; + case 8: bkpt8(); break; + case 9: bkpt9(); break; + case 10: bkpt10(); break; + case 11: bkpt11(); break; + case 12: bkpt12(); break; + case 13: bkpt13(); break; + case 14: bkpt14(); break; + case 15: bkpt15(); break; + case 16: bkpt16(); break; + case 17: bkpt17(); break; + case 18: bkpt18(); break; + case 19: bkpt19(); break; + case 20: bkpt20(); break; + case 21: bkpt21(); break; + case 22: bkpt22(); break; + case 23: bkpt23(); break; + case 24: bkpt24(); break; + case 25: bkpt25(); break; + case 26: bkpt26(); break; + case 27: bkpt27(); break; + case 28: bkpt28(); break; + case 29: bkpt29(); break; } + System.out.println("Thread " + threadName + " You entered : " + s); + } - ); + } catch (Exception e) { + System.out.println("WOOPS"); + } + }); thrd.setName(threadName); thrd.setPriority(Thread.MAX_PRIORITY-1); thrd.start(); diff --git a/test/jdk/com/sun/security/sasl/ClientCallbackHandler.java b/test/jdk/com/sun/security/sasl/ClientCallbackHandler.java index 33a4be4823a..23ee550a2a7 100644 --- a/test/jdk/com/sun/security/sasl/ClientCallbackHandler.java +++ b/test/jdk/com/sun/security/sasl/ClientCallbackHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,6 +130,6 @@ public void handle(Callback[] callbacks) throws UnsupportedCallbackException, /* Reads a line of input */ private String readLine() throws IOException { return new BufferedReader - (new InputStreamReader(System.in)).readLine(); + (new InputStreamReader(System.in, System.getProperty("stdin.encoding"))).readLine(); } } diff --git a/test/jdk/com/sun/security/sasl/digest/ClientCallbackHandler.java b/test/jdk/com/sun/security/sasl/digest/ClientCallbackHandler.java index 33a4be4823a..23ee550a2a7 100644 --- a/test/jdk/com/sun/security/sasl/digest/ClientCallbackHandler.java +++ b/test/jdk/com/sun/security/sasl/digest/ClientCallbackHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,6 +130,6 @@ public void handle(Callback[] callbacks) throws UnsupportedCallbackException, /* Reads a line of input */ private String readLine() throws IOException { return new BufferedReader - (new InputStreamReader(System.in)).readLine(); + (new InputStreamReader(System.in, System.getProperty("stdin.encoding"))).readLine(); } } diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index ed9a0f9fb70..1995e9cecd1 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -337,7 +337,7 @@ public static void main(String args[]) throws Throwable { } else if (action.equals("testIO")) { String expected = "standard input"; char[] buf = new char[expected.length()+1]; - int n = new InputStreamReader(System.in).read(buf,0,buf.length); + int n = new InputStreamReader(System.in, System.getProperty("stdin.encoding")).read(buf,0,buf.length); if (n != expected.length()) System.exit(5); if (! new String(buf,0,n).equals(expected)) diff --git a/test/jdk/java/nio/charset/spi/CharsetTest.java b/test/jdk/java/nio/charset/spi/CharsetTest.java index 4ac3d14b1d3..c6932d36bd7 100644 --- a/test/jdk/java/nio/charset/spi/CharsetTest.java +++ b/test/jdk/java/nio/charset/spi/CharsetTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,6 +21,7 @@ * questions. */ +import java.io.ByteArrayInputStream; import java.io.InputStreamReader; import java.io.PrintStream; import java.nio.charset.Charset; @@ -72,8 +73,10 @@ private static void testNegative(String csn) { public static void main(String [] args) { - out.println("Default: " - + new InputStreamReader(System.in).getEncoding()); + for (String property : new String[]{"stdin.encoding", "stdout.encoding", "stderr.encoding"}) { + String name = System.getProperty(property); + out.printf("%s: %s (%s)%n", property, name, Charset.forName(name)); + } out.print("Available:"); for (Iterator i = available.keySet().iterator(); i.hasNext();) From d8c3533a91aa9c3a0b76846fe425c72bda9bd66c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Maillard?= Date: Mon, 16 Jun 2025 07:29:06 +0000 Subject: [PATCH 064/213] 8357816: Add test from JDK-8350576 Co-authored-by: Tobias Hartmann Reviewed-by: syan, thartmann, epeter --- .../LoopReductionHasControlOrBadInput.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/LoopReductionHasControlOrBadInput.java diff --git a/test/hotspot/jtreg/compiler/loopopts/LoopReductionHasControlOrBadInput.java b/test/hotspot/jtreg/compiler/loopopts/LoopReductionHasControlOrBadInput.java new file mode 100644 index 00000000000..b30939412f0 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/LoopReductionHasControlOrBadInput.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8350576 + * @summary Optimization bails out and hits an assert: + * assert(false) failed: reduction has ctrl or bad vector_input + * @run main/othervm -Xbatch -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,compiler.loopopts.LoopReductionHasControlOrBadInput::* + * compiler.loopopts.LoopReductionHasControlOrBadInput + * @run main compiler.loopopts.LoopReductionHasControlOrBadInput + * + */ + +package compiler.loopopts; + +public class LoopReductionHasControlOrBadInput { + static long lFld; + static long lArr[] = new long[400]; + + static void test() { + int i = 1; + do { + long x = -1; + lArr[i] = i; + lFld += i | x; + } while (++i < 355); + } + + public static void main(String[] strArr) { + for (int i = 0; i < 100; i++) { + test(); + } + } +} From 8416ca3104d98edad89ed20bdb203a36974f410a Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 16 Jun 2025 07:29:24 +0000 Subject: [PATCH 065/213] 8346982: Remove JMX javadoc duplication that was in place due to JDK-6369229 Reviewed-by: amenkov --- .../javax/management/ImmutableDescriptor.java | 46 ------------------ .../modelmbean/DescriptorSupport.java | 47 ------------------- 2 files changed, 93 deletions(-) diff --git a/src/java.management/share/classes/javax/management/ImmutableDescriptor.java b/src/java.management/share/classes/javax/management/ImmutableDescriptor.java index c9044b68ed2..ff90068958f 100644 --- a/src/java.management/share/classes/javax/management/ImmutableDescriptor.java +++ b/src/java.management/share/classes/javax/management/ImmutableDescriptor.java @@ -343,30 +343,6 @@ public final String[] getFieldNames() { return names.clone(); } - /** - * Compares this descriptor to the given object. The objects are equal if - * the given object is also a Descriptor, and if the two Descriptors have - * the same field names (possibly differing in case) and the same - * associated values. The respective values for a field in the two - * Descriptors are equal if the following conditions hold: - * - *

      - *
    • If one value is null then the other must be too.
    • - *
    • If one value is a primitive array then the other must be a primitive - * array of the same type with the same elements.
    • - *
    • If one value is an object array then the other must be too and - * {@link Arrays#deepEquals(Object[],Object[])} must return true.
    • - *
    • Otherwise {@link Object#equals(Object)} must return true.
    • - *
    - * - * @param o the object to compare with. - * - * @return {@code true} if the objects are the same; {@code false} - * otherwise. - * - */ - // Note: this Javadoc is copied from javax.management.Descriptor - // due to 6369229. @Override public boolean equals(Object o) { if (o == this) @@ -394,28 +370,6 @@ public boolean equals(Object o) { return Arrays.deepEquals(values, ovalues); } - /** - *

    Returns the hash code value for this descriptor. The hash - * code is computed as the sum of the hash codes for each field in - * the descriptor. The hash code of a field with name {@code n} - * and value {@code v} is {@code n.toLowerCase().hashCode() ^ h}. - * Here {@code h} is the hash code of {@code v}, computed as - * follows:

    - * - *
      - *
    • If {@code v} is null then {@code h} is 0.
    • - *
    • If {@code v} is a primitive array then {@code h} is computed using - * the appropriate overloading of {@code java.util.Arrays.hashCode}.
    • - *
    • If {@code v} is an object array then {@code h} is computed using - * {@link Arrays#deepHashCode(Object[])}.
    • - *
    • Otherwise {@code h} is {@code v.hashCode()}.
    • - *
    - * - * @return A hash code value for this object. - * - */ - // Note: this Javadoc is copied from javax.management.Descriptor - // due to 6369229. @Override public int hashCode() { if (hashCode == -1) { diff --git a/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java b/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java index d003cd9d9d6..71f8f61bedb 100644 --- a/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java +++ b/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java @@ -696,31 +696,6 @@ public synchronized void removeField(String fieldName) { descriptorMap.remove(fieldName); } - /** - * Compares this descriptor to the given object. The objects are equal if - * the given object is also a Descriptor, and if the two Descriptors have - * the same field names (possibly differing in case) and the same - * associated values. The respective values for a field in the two - * Descriptors are equal if the following conditions hold: - * - *
      - *
    • If one value is null then the other must be too.
    • - *
    • If one value is a primitive array then the other must be a primitive - * array of the same type with the same elements.
    • - *
    • If one value is an object array then the other must be too and - * {@link java.util.Arrays#deepEquals(Object[],Object[]) Arrays.deepEquals} - * must return true.
    • - *
    • Otherwise {@link Object#equals(Object)} must return true.
    • - *
    - * - * @param o the object to compare with. - * - * @return {@code true} if the objects are the same; {@code false} - * otherwise. - * - */ - // Note: this Javadoc is copied from javax.management.Descriptor - // due to 6369229. @Override public synchronized boolean equals(Object o) { if (o == this) @@ -732,28 +707,6 @@ public synchronized boolean equals(Object o) { return new ImmutableDescriptor(descriptorMap).equals(o); } - /** - *

    Returns the hash code value for this descriptor. The hash - * code is computed as the sum of the hash codes for each field in - * the descriptor. The hash code of a field with name {@code n} - * and value {@code v} is {@code n.toLowerCase().hashCode() ^ h}. - * Here {@code h} is the hash code of {@code v}, computed as - * follows:

    - * - *
      - *
    • If {@code v} is null then {@code h} is 0.
    • - *
    • If {@code v} is a primitive array then {@code h} is computed using - * the appropriate overloading of {@code java.util.Arrays.hashCode}.
    • - *
    • If {@code v} is an object array then {@code h} is computed using - * {@link java.util.Arrays#deepHashCode(Object[]) Arrays.deepHashCode}.
    • - *
    • Otherwise {@code h} is {@code v.hashCode()}.
    • - *
    - * - * @return A hash code value for this object. - * - */ - // Note: this Javadoc is copied from javax.management.Descriptor - // due to 6369229. @Override public synchronized int hashCode() { final int size = descriptorMap.size(); From 79497ef7f55ef445b31348ae9d3d6dff6d3b6a54 Mon Sep 17 00:00:00 2001 From: Suchismith Roy Date: Mon, 16 Jun 2025 08:30:41 +0000 Subject: [PATCH 066/213] 8348574: Simplify c1/c2_globals inclusions Reviewed-by: mhaessig, kbarrett --- src/hotspot/os/aix/c1_globals_aix.hpp | 37 ------------------- src/hotspot/os/aix/c2_globals_aix.hpp | 37 ------------------- src/hotspot/os/bsd/c1_globals_bsd.hpp | 36 ------------------ src/hotspot/os/bsd/c2_globals_bsd.hpp | 36 ------------------ src/hotspot/os/linux/c1_globals_linux.hpp | 36 ------------------ src/hotspot/os/linux/c2_globals_linux.hpp | 36 ------------------ src/hotspot/os/windows/c1_globals_windows.hpp | 36 ------------------ src/hotspot/os/windows/c2_globals_windows.hpp | 36 ------------------ src/hotspot/share/c1/c1_globals.hpp | 4 +- src/hotspot/share/c1/c1_globals_pd.hpp | 34 ----------------- .../share/compiler/compiler_globals_pd.hpp | 6 +-- src/hotspot/share/opto/c2_globals.hpp | 2 +- src/hotspot/share/opto/c2_globals_pd.hpp | 34 ----------------- 13 files changed, 6 insertions(+), 364 deletions(-) delete mode 100644 src/hotspot/os/aix/c1_globals_aix.hpp delete mode 100644 src/hotspot/os/aix/c2_globals_aix.hpp delete mode 100644 src/hotspot/os/bsd/c1_globals_bsd.hpp delete mode 100644 src/hotspot/os/bsd/c2_globals_bsd.hpp delete mode 100644 src/hotspot/os/linux/c1_globals_linux.hpp delete mode 100644 src/hotspot/os/linux/c2_globals_linux.hpp delete mode 100644 src/hotspot/os/windows/c1_globals_windows.hpp delete mode 100644 src/hotspot/os/windows/c2_globals_windows.hpp delete mode 100644 src/hotspot/share/c1/c1_globals_pd.hpp delete mode 100644 src/hotspot/share/opto/c2_globals_pd.hpp diff --git a/src/hotspot/os/aix/c1_globals_aix.hpp b/src/hotspot/os/aix/c1_globals_aix.hpp deleted file mode 100644 index 1d5cf980104..00000000000 --- a/src/hotspot/os/aix/c1_globals_aix.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_AIX_C1_GLOBALS_AIX_HPP -#define OS_AIX_C1_GLOBALS_AIX_HPP - -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" - -// -// Sets the default values for operating system dependent flags used by the -// client compiler. (see c1_globals.hpp) -// - -#endif // OS_AIX_C1_GLOBALS_AIX_HPP diff --git a/src/hotspot/os/aix/c2_globals_aix.hpp b/src/hotspot/os/aix/c2_globals_aix.hpp deleted file mode 100644 index 8bc2a6cdd55..00000000000 --- a/src/hotspot/os/aix/c2_globals_aix.hpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef OS_AIX_C2_GLOBALS_AIX_HPP -#define OS_AIX_C2_GLOBALS_AIX_HPP - -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" - -// -// Sets the default values for operating system dependent flags used by the -// server compiler. (see c2_globals.hpp) -// - -#endif // OS_AIX_C2_GLOBALS_AIX_HPP diff --git a/src/hotspot/os/bsd/c1_globals_bsd.hpp b/src/hotspot/os/bsd/c1_globals_bsd.hpp deleted file mode 100644 index aa24414612a..00000000000 --- a/src/hotspot/os/bsd/c1_globals_bsd.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. - * 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 OS_BSD_C1_GLOBALS_BSD_HPP -#define OS_BSD_C1_GLOBALS_BSD_HPP - -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" - -// -// Sets the default values for operating system dependent flags used by the -// client compiler. (see c1_globals.hpp) -// - -#endif // OS_BSD_C1_GLOBALS_BSD_HPP diff --git a/src/hotspot/os/bsd/c2_globals_bsd.hpp b/src/hotspot/os/bsd/c2_globals_bsd.hpp deleted file mode 100644 index 1e8a89ef4a8..00000000000 --- a/src/hotspot/os/bsd/c2_globals_bsd.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. - * 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 OS_BSD_C2_GLOBALS_BSD_HPP -#define OS_BSD_C2_GLOBALS_BSD_HPP - -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" - -// -// Sets the default values for operating system dependent flags used by the -// server compiler. (see c2_globals.hpp) -// - -#endif // OS_BSD_C2_GLOBALS_BSD_HPP diff --git a/src/hotspot/os/linux/c1_globals_linux.hpp b/src/hotspot/os/linux/c1_globals_linux.hpp deleted file mode 100644 index 8f7f0e367d7..00000000000 --- a/src/hotspot/os/linux/c1_globals_linux.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. - * 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 OS_LINUX_C1_GLOBALS_LINUX_HPP -#define OS_LINUX_C1_GLOBALS_LINUX_HPP - -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" - -// -// Sets the default values for operating system dependent flags used by the -// client compiler. (see c1_globals.hpp) -// - -#endif // OS_LINUX_C1_GLOBALS_LINUX_HPP diff --git a/src/hotspot/os/linux/c2_globals_linux.hpp b/src/hotspot/os/linux/c2_globals_linux.hpp deleted file mode 100644 index c6199253f3e..00000000000 --- a/src/hotspot/os/linux/c2_globals_linux.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. - * 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 OS_LINUX_C2_GLOBALS_LINUX_HPP -#define OS_LINUX_C2_GLOBALS_LINUX_HPP - -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" - -// -// Sets the default values for operating system dependent flags used by the -// server compiler. (see c2_globals.hpp) -// - -#endif // OS_LINUX_C2_GLOBALS_LINUX_HPP diff --git a/src/hotspot/os/windows/c1_globals_windows.hpp b/src/hotspot/os/windows/c1_globals_windows.hpp deleted file mode 100644 index 06e6da5d68c..00000000000 --- a/src/hotspot/os/windows/c1_globals_windows.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. - * 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 OS_WINDOWS_C1_GLOBALS_WINDOWS_HPP -#define OS_WINDOWS_C1_GLOBALS_WINDOWS_HPP - -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" - -// -// Sets the default values for operating system dependent flags used by the -// client compiler. (see c1_globals.hpp) -// - -#endif // OS_WINDOWS_C1_GLOBALS_WINDOWS_HPP diff --git a/src/hotspot/os/windows/c2_globals_windows.hpp b/src/hotspot/os/windows/c2_globals_windows.hpp deleted file mode 100644 index 6891113d2cd..00000000000 --- a/src/hotspot/os/windows/c2_globals_windows.hpp +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. - * 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 OS_WINDOWS_C2_GLOBALS_WINDOWS_HPP -#define OS_WINDOWS_C2_GLOBALS_WINDOWS_HPP - -#include "utilities/globalDefinitions.hpp" -#include "utilities/macros.hpp" - -// -// Sets the default values for operating system dependent flags used by the -// server compiler. (see c2_globals.hpp) -// - -#endif // OS_WINDOWS_C2_GLOBALS_WINDOWS_HPP diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index ec01bc7a790..ad259c8cc4e 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,9 @@ #ifndef SHARE_C1_C1_GLOBALS_HPP #define SHARE_C1_C1_GLOBALS_HPP -#include "c1/c1_globals_pd.hpp" #include "runtime/globals_shared.hpp" #include "utilities/macros.hpp" +#include CPU_HEADER(c1_globals) // // Declare all global flags used by the client compiler. // diff --git a/src/hotspot/share/c1/c1_globals_pd.hpp b/src/hotspot/share/c1/c1_globals_pd.hpp deleted file mode 100644 index fcf78b95272..00000000000 --- a/src/hotspot/share/c1/c1_globals_pd.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * 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_C1_C1_GLOBALS_PD_HPP -#define SHARE_C1_C1_GLOBALS_PD_HPP - -#include "runtime/globals_shared.hpp" -#include "utilities/macros.hpp" - -#include CPU_HEADER(c1_globals) -#include OS_HEADER(c1_globals) - -#endif // SHARE_C1_C1_GLOBALS_PD_HPP diff --git a/src/hotspot/share/compiler/compiler_globals_pd.hpp b/src/hotspot/share/compiler/compiler_globals_pd.hpp index 1251329a1b6..f27033c0607 100644 --- a/src/hotspot/share/compiler/compiler_globals_pd.hpp +++ b/src/hotspot/share/compiler/compiler_globals_pd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,10 @@ #include "runtime/globals_shared.hpp" #ifdef COMPILER1 -#include "c1/c1_globals_pd.hpp" +#include "c1/c1_globals.hpp" #endif // COMPILER1 #ifdef COMPILER2 -#include "opto/c2_globals_pd.hpp" +#include "opto/c2_globals.hpp" #endif // COMPILER2 // JVMCI has no platform-specific global definitions diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 227817612ce..ca76114af31 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -25,9 +25,9 @@ #ifndef SHARE_OPTO_C2_GLOBALS_HPP #define SHARE_OPTO_C2_GLOBALS_HPP -#include "opto/c2_globals_pd.hpp" #include "runtime/globals_shared.hpp" #include "utilities/macros.hpp" +#include CPU_HEADER(c2_globals) // // Defines all globals flags used by the server compiler. diff --git a/src/hotspot/share/opto/c2_globals_pd.hpp b/src/hotspot/share/opto/c2_globals_pd.hpp deleted file mode 100644 index c2ab269cebf..00000000000 --- a/src/hotspot/share/opto/c2_globals_pd.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * 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_OPTO_C2_GLOBALS_PD_HPP -#define SHARE_OPTO_C2_GLOBALS_PD_HPP - -#include "runtime/globals_shared.hpp" -#include "utilities/macros.hpp" - -#include CPU_HEADER(c2_globals) -#include OS_HEADER(c2_globals) - -#endif // SHARE_OPTO_C2_GLOBALS_PD_HPP From fedd0a0ee3aea9f73cfce34172a764e63c1ba46b Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 16 Jun 2025 09:09:55 +0000 Subject: [PATCH 067/213] 8359248: JFR: Help text for-XX:StartFlightRecording:report-on-exit should explain option can be repeated Reviewed-by: mgronlun --- src/java.base/share/man/java.md | 7 ++++--- .../share/classes/jdk/jfr/internal/dcmd/DCmdStart.java | 8 +++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index fc8cbb23aff..b8c8011eb47 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -1449,9 +1449,10 @@ These `java` options control the runtime behavior of the Java HotSpot VM. `report-on-exit=`*identifier* : Specifies the name of the view to display when the Java Virtual Machine - (JVM) shuts down. This option is not available if the disk option is set - to false. For a list of available views, see `jfr help view`. By default, - no report is generated. + (JVM) shuts down. To specify more than one view, use the report-on-exit + parameter repeatedly. This option is not available if the disk option + is set to false. For a list of available views, see `jfr help view`. + By default, no report is generated. `settings=`*path* : Specifies the path and name of the event settings file (of type JFC). diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java index 9cc3bdaf101..ed93710e59a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/dcmd/DCmdStart.java @@ -502,9 +502,11 @@ private static String reportOnExit() { """ report-on-exit Specifies the name of the view to display when the Java Virtual - Machine (JVM) shuts down. This option is not available if the - disk option is set to false. For a list of available views, - see 'jfr help view'. By default, no report is generated. + Machine (JVM) shuts down. To specify more than one view, use + the `report-on-exit` parameter repeatedly, for each view. This + option is not available if the disk option is set to false. + For a list of available views, see `jfr help view`. By default, + no report is generated. """; } From 9d060574e5dbd13e634f00d749d0108ceff1fae8 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Mon, 16 Jun 2025 10:20:25 +0000 Subject: [PATCH 068/213] 8358892: RISC-V: jvm crash when running dacapo sunflow after JDK-8352504 8359045: RISC-V: construct test to verify invocation of C2_MacroAssembler::enc_cmove_cmp_fp => BoolTest::ge/gt Co-authored-by: Fei Yang Reviewed-by: fyang, fjiang --- .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 6 +- .../cpu/riscv/macroAssembler_riscv.cpp | 94 +- .../cpu/riscv/macroAssembler_riscv.hpp | 2 + .../c2/irTests/TestFPComparison2.java | 1005 +++++++++++++++++ 4 files changed, 1073 insertions(+), 34 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index 77b4e26cc92..ce13ebde74f 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -2170,15 +2170,13 @@ void C2_MacroAssembler::enc_cmove_cmp_fp(int cmpFlag, FloatRegister op1, FloatRe cmov_cmp_fp_le(op1, op2, dst, src, is_single); break; case BoolTest::ge: - assert(false, "Should go to BoolTest::le case"); - ShouldNotReachHere(); + cmov_cmp_fp_ge(op1, op2, dst, src, is_single); break; case BoolTest::lt: cmov_cmp_fp_lt(op1, op2, dst, src, is_single); break; case BoolTest::gt: - assert(false, "Should go to BoolTest::lt case"); - ShouldNotReachHere(); + cmov_cmp_fp_gt(op1, op2, dst, src, is_single); break; default: assert(false, "unsupported compare condition"); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 7c5b2cdbf1d..d44e7daa563 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -1268,12 +1268,19 @@ void MacroAssembler::cmov_gtu(Register cmp1, Register cmp2, Register dst, Regist } // ----------- cmove, compare float ----------- +// +// For CmpF/D + CMoveI/L, ordered ones are quite straight and simple, +// so, just list behaviour of unordered ones as follow. +// +// Set dst (CMoveI (Binary cop (CmpF/D op1 op2)) (Binary dst src)) +// (If one or both inputs to the compare are NaN, then) +// 1. (op1 lt op2) => true => CMove: dst = src +// 2. (op1 le op2) => true => CMove: dst = src +// 3. (op1 gt op2) => false => CMove: dst = dst +// 4. (op1 ge op2) => false => CMove: dst = dst +// 5. (op1 eq op2) => false => CMove: dst = dst +// 6. (op1 ne op2) => true => CMove: dst = src -// Move src to dst only if cmp1 == cmp2, -// otherwise leave dst unchanged, including the case where one of them is NaN. -// Clarification: -// java code : cmp1 != cmp2 ? dst : src -// transformed to : CMove dst, (cmp1 eq cmp2), dst, src void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { if (UseZicond) { if (is_single) { @@ -1289,7 +1296,7 @@ void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Regi Label no_set; if (is_single) { // jump if cmp1 != cmp2, including the case of NaN - // not jump (i.e. move src to dst) if cmp1 == cmp2 + // fallthrough (i.e. move src to dst) if cmp1 == cmp2 float_bne(cmp1, cmp2, no_set); } else { double_bne(cmp1, cmp2, no_set); @@ -1298,11 +1305,6 @@ void MacroAssembler::cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Regi bind(no_set); } -// Keep dst unchanged only if cmp1 == cmp2, -// otherwise move src to dst, including the case where one of them is NaN. -// Clarification: -// java code : cmp1 == cmp2 ? dst : src -// transformed to : CMove dst, (cmp1 ne cmp2), dst, src void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { if (UseZicond) { if (is_single) { @@ -1318,7 +1320,7 @@ void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Regi Label no_set; if (is_single) { // jump if cmp1 == cmp2 - // not jump (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN + // fallthrough (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN float_beq(cmp1, cmp2, no_set); } else { double_beq(cmp1, cmp2, no_set); @@ -1327,14 +1329,6 @@ void MacroAssembler::cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Regi bind(no_set); } -// When cmp1 <= cmp2 or any of them is NaN then dst = src, otherwise, dst = dst -// Clarification -// scenario 1: -// java code : cmp2 < cmp1 ? dst : src -// transformed to : CMove dst, (cmp1 le cmp2), dst, src -// scenario 2: -// java code : cmp1 > cmp2 ? dst : src -// transformed to : CMove dst, (cmp1 le cmp2), dst, src void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { if (UseZicond) { if (is_single) { @@ -1350,7 +1344,7 @@ void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Regi Label no_set; if (is_single) { // jump if cmp1 > cmp2 - // not jump (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN + // fallthrough (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN float_bgt(cmp1, cmp2, no_set); } else { double_bgt(cmp1, cmp2, no_set); @@ -1359,14 +1353,30 @@ void MacroAssembler::cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Regi bind(no_set); } -// When cmp1 < cmp2 or any of them is NaN then dst = src, otherwise, dst = dst -// Clarification -// scenario 1: -// java code : cmp2 <= cmp1 ? dst : src -// transformed to : CMove dst, (cmp1 lt cmp2), dst, src -// scenario 2: -// java code : cmp1 >= cmp2 ? dst : src -// transformed to : CMove dst, (cmp1 lt cmp2), dst, src +void MacroAssembler::cmov_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { + if (UseZicond) { + if (is_single) { + fle_s(t0, cmp2, cmp1); + } else { + fle_d(t0, cmp2, cmp1); + } + czero_nez(dst, dst, t0); + czero_eqz(t0 , src, t0); + orr(dst, dst, t0); + return; + } + Label no_set; + if (is_single) { + // jump if cmp1 < cmp2 or either is NaN + // fallthrough (i.e. move src to dst) if cmp1 >= cmp2 + float_blt(cmp1, cmp2, no_set, false, true); + } else { + double_blt(cmp1, cmp2, no_set, false, true); + } + mv(dst, src); + bind(no_set); +} + void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { if (UseZicond) { if (is_single) { @@ -1382,7 +1392,7 @@ void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Regi Label no_set; if (is_single) { // jump if cmp1 >= cmp2 - // not jump (i.e. move src to dst) if cmp1 < cmp2 or either is NaN + // fallthrough (i.e. move src to dst) if cmp1 < cmp2 or either is NaN float_bge(cmp1, cmp2, no_set); } else { double_bge(cmp1, cmp2, no_set); @@ -1391,6 +1401,30 @@ void MacroAssembler::cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Regi bind(no_set); } +void MacroAssembler::cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single) { + if (UseZicond) { + if (is_single) { + flt_s(t0, cmp2, cmp1); + } else { + flt_d(t0, cmp2, cmp1); + } + czero_nez(dst, dst, t0); + czero_eqz(t0 , src, t0); + orr(dst, dst, t0); + return; + } + Label no_set; + if (is_single) { + // jump if cmp1 <= cmp2 or either is NaN + // fallthrough (i.e. move src to dst) if cmp1 > cmp2 + float_ble(cmp1, cmp2, no_set, false, true); + } else { + double_ble(cmp1, cmp2, no_set, false, true); + } + mv(dst, src); + bind(no_set); +} + // Float compare branch instructions #define INSN(NAME, FLOATCMP, BRANCH) \ diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index fc60bc67b4e..e61d9d5e097 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -660,7 +660,9 @@ class MacroAssembler: public Assembler { void cmov_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); void cmov_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); void cmov_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); + void cmov_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); void cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); + void cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); public: // We try to follow risc-v asm menomics. diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java b/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java new file mode 100644 index 00000000000..59c70b6873f --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java @@ -0,0 +1,1005 @@ +/* + * Copyright (c) 2025, Rivos Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests; + +import compiler.lib.ir_framework.*; +import java.util.List; + +/* + * @test + * @bug 8358892 + * @summary The test is to trigger code path of BoolTest::ge/gt in C2_MacroAssembler::enc_cmove_cmp_fp + * @requires os.arch == "riscv64" + * @requires vm.debug + * @library /test/lib / + * @run driver compiler.c2.irTests.TestFPComparison2 + */ +public class TestFPComparison2 { + static final double[] DOUBLES = new double[] { + Double.NEGATIVE_INFINITY, + -Double.MAX_VALUE, + -1.0, + -Double.MIN_VALUE, + -0.0, + 0.0, + Double.MIN_VALUE, + 1.0, + Double.MAX_VALUE, + Double.POSITIVE_INFINITY, + Double.NaN, + }; + + static final float[] FLOATS = new float[] { + Float.NEGATIVE_INFINITY, + -Float.MAX_VALUE, + -1.0F, + -Float.MIN_VALUE, + -0.0F, + 0.0F, + Float.MIN_VALUE, + 1.0F, + Float.MAX_VALUE, + Float.POSITIVE_INFINITY, + Float.NaN, + }; + + static final int[] INTS = new int[] { + Integer.MIN_VALUE, + -100, + -1, + 0, + 1, + 100, + Integer.MAX_VALUE, + }; + + public static void main(String[] args) { + List options = List.of("-XX:-TieredCompilation", "-Xlog:jit+compilation=trace"); + // Booltest::ge + TestFramework framework = new TestFramework(Test_ge_1.class); + framework.addFlags(options.toArray(new String[0])).start(); + + framework = new TestFramework(Test_ge_2.class); + framework.addFlags(options.toArray(new String[0])).start(); + + // Booltest::gt + framework = new TestFramework(Test_gt_1.class); + framework.addFlags(options.toArray(new String[0])).start(); + + framework = new TestFramework(Test_gt_2.class); + framework.addFlags(options.toArray(new String[0])).start(); + } +} + +class Test_ge_1 { + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_ge_fixed_1_0(float x, float y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x > y + // return 0 + // when neither is NaN, and x <= y + return !(x <= y) ? 1 : 0; + } + @DontCompile + public static int golden_float_BoolTest_ge_fixed_1_0(float x, float y) { + return !(x <= y) ? 1 : 0; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_ge_fixed_1_0(double x, double y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x > y + // return 0 + // when neither is NaN, and x <= y + return !(x <= y) ? 1 : 0; + } + @DontCompile + public static int golden_double_BoolTest_ge_fixed_1_0(double x, double y) { + return !(x <= y) ? 1 : 0; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_ge_fixed_0_1(float x, float y) { + return !(x <= y) ? 0 : 1; + } + @DontCompile + public static int golden_float_BoolTest_ge_fixed_0_1(float x, float y) { + return !(x <= y) ? 0 : 1; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_ge_fixed_0_1(double x, double y) { + return !(x <= y) ? 0 : 1; + } + @DontCompile + public static int golden_double_BoolTest_ge_fixed_0_1(double x, double y) { + return !(x <= y) ? 0 : 1; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_ge_fixed_10_20(float x, float y) { + return !(x <= y) ? 10 : 20; + } + @DontCompile + public static int golden_float_BoolTest_ge_fixed_10_20(float x, float y) { + return !(x <= y) ? 10 : 20; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_ge_fixed_10_20(double x, double y) { + return !(x <= y) ? 10 : 20; + } + @DontCompile + public static int golden_double_BoolTest_ge_fixed_10_20(double x, double y) { + return !(x <= y) ? 10 : 20; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_ge_variable_results(float x, float y, int a, int b) { + return !(x <= y) ? a : b; + } + @DontCompile + public static int golden_float_BoolTest_ge_variable_results(float x, float y, int a, int b) { + return !(x <= y) ? a : b; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_ge_variable_results(double x, double y, int a, int b) { + return !(x <= y) ? a : b; + } + @DontCompile + public static int golden_double_BoolTest_ge_variable_results(double x, double y, int a, int b) { + return !(x <= y) ? a : b; + } + + @Run(test = {"test_float_BoolTest_ge_fixed_1_0", "test_double_BoolTest_ge_fixed_1_0", + "test_float_BoolTest_ge_fixed_0_1", "test_double_BoolTest_ge_fixed_0_1", + "test_float_BoolTest_ge_fixed_10_20", "test_double_BoolTest_ge_fixed_10_20", + "test_float_BoolTest_ge_variable_results", "test_double_BoolTest_ge_variable_results"}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_ge_fixed_1_0(x, y); + int expected = golden_float_BoolTest_ge_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 1, 0), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_ge_fixed_1_0(x, y); + int expected = golden_double_BoolTest_ge_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 1, 0), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_ge_fixed_0_1(x, y); + int expected = golden_float_BoolTest_ge_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_ge_fixed_0_1(x, y); + int expected = golden_double_BoolTest_ge_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_ge_fixed_10_20(x, y); + int expected = golden_float_BoolTest_ge_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_ge_fixed_10_20(x, y); + int expected = golden_double_BoolTest_ge_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + for (int m = 0; m < TestFPComparison2.INTS.length; m++) { + for (int n = 0; n < TestFPComparison2.INTS.length; n++) { + int a = TestFPComparison2.INTS[m]; + int b = TestFPComparison2.INTS[n]; + int actual = test_float_BoolTest_ge_variable_results(x, y, a, b); + int expected = golden_float_BoolTest_ge_variable_results(x, y, a, b); + if (actual != expected) { + System.out.println("Float failed (ge), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + for (int m = 0; m < TestFPComparison2.INTS.length; m++) { + for (int n = 0; n < TestFPComparison2.INTS.length; n++) { + int a = TestFPComparison2.INTS[m]; + int b = TestFPComparison2.INTS[n]; + int actual = test_double_BoolTest_ge_variable_results(x, y, a, b); + int expected = golden_double_BoolTest_ge_variable_results(x, y, a, b); + if (actual != expected) { + System.out.println("Double failed (ge), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} + +class Test_ge_2 { + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_ge_fixed_1_0(float x, float y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x < y + // return 0 + // when neither is NaN, and x >= y + return !(x >= y) ? 1 : 0; + } + @DontCompile + public static int golden_float_BoolTest_ge_fixed_1_0(float x, float y) { + return !(x >= y) ? 1 : 0; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_ge_fixed_1_0(double x, double y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x < y + // return 0 + // when neither is NaN, and x >= y + return !(x >= y) ? 1 : 0; + } + @DontCompile + public static int golden_double_BoolTest_ge_fixed_1_0(double x, double y) { + return !(x >= y) ? 1 : 0; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_ge_fixed_0_1(float x, float y) { + return !(x >= y) ? 0 : 1; + } + @DontCompile + public static int golden_float_BoolTest_ge_fixed_0_1(float x, float y) { + return !(x >= y) ? 0 : 1; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_ge_fixed_0_1(double x, double y) { + return !(x >= y) ? 0 : 1; + } + @DontCompile + public static int golden_double_BoolTest_ge_fixed_0_1(double x, double y) { + return !(x >= y) ? 0 : 1; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_ge_fixed_10_20(float x, float y) { + return !(x >= y) ? 10 : 20; + } + @DontCompile + public static int golden_float_BoolTest_ge_fixed_10_20(float x, float y) { + return !(x >= y) ? 10 : 20; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_ge_fixed_10_20(double x, double y) { + return !(x >= y) ? 10 : 20; + } + @DontCompile + public static int golden_double_BoolTest_ge_fixed_10_20(double x, double y) { + return !(x >= y) ? 10 : 20; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_ge_variable_results(float x, float y, int a, int b) { + return !(x >= y) ? a : b; + } + @DontCompile + public static int golden_float_BoolTest_ge_variable_results(float x, float y, int a, int b) { + return !(x >= y) ? a : b; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_ge_variable_results(double x, double y, int a, int b) { + return !(x >= y) ? a : b; + } + @DontCompile + public static int golden_double_BoolTest_ge_variable_results(double x, double y, int a, int b) { + return !(x >= y) ? a : b; + } + + @Run(test = {"test_float_BoolTest_ge_fixed_1_0", "test_double_BoolTest_ge_fixed_1_0", + "test_float_BoolTest_ge_fixed_0_1", "test_double_BoolTest_ge_fixed_0_1", + "test_float_BoolTest_ge_fixed_10_20", "test_double_BoolTest_ge_fixed_10_20", + "test_float_BoolTest_ge_variable_results", "test_double_BoolTest_ge_variable_results"}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_ge_fixed_1_0(x, y); + int expected = golden_float_BoolTest_ge_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Float failed (ge), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_ge_fixed_1_0(x, y); + int expected = golden_double_BoolTest_ge_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Double failed (ge), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_ge_fixed_0_1(x, y); + int expected = golden_float_BoolTest_ge_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_ge_fixed_0_1(x, y); + int expected = golden_double_BoolTest_ge_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_ge_fixed_10_20(x, y); + int expected = golden_float_BoolTest_ge_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_ge_fixed_10_20(x, y); + int expected = golden_double_BoolTest_ge_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + for (int m = 0; m < TestFPComparison2.INTS.length; m++) { + for (int n = 0; n < TestFPComparison2.INTS.length; n++) { + int a = TestFPComparison2.INTS[m]; + int b = TestFPComparison2.INTS[n]; + int actual = test_float_BoolTest_ge_variable_results(x, y, a, b); + int expected = golden_float_BoolTest_ge_variable_results(x, y, a, b); + if (actual != expected) { + System.out.println("Float failed (ge), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + for (int m = 0; m < TestFPComparison2.INTS.length; m++) { + for (int n = 0; n < TestFPComparison2.INTS.length; n++) { + int a = TestFPComparison2.INTS[m]; + int b = TestFPComparison2.INTS[n]; + int actual = test_double_BoolTest_ge_variable_results(x, y, a, b); + int expected = golden_double_BoolTest_ge_variable_results(x, y, a, b); + if (actual != expected) { + System.out.println("Double failed (ge), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} + +class Test_gt_1 { + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_gt_fixed_1_0(float x, float y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x >= y + // return 0 + // when neither is NaN, and x < y + return !(x < y) ? 1 : 0; + } + @DontCompile + public static int golden_float_BoolTest_gt_fixed_1_0(float x, float y) { + return !(x < y) ? 1 : 0; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_gt_fixed_1_0(double x, double y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x >= y + // return 0 + // when neither is NaN, and x < y + return !(x < y) ? 1 : 0; + } + @DontCompile + public static int golden_double_BoolTest_gt_fixed_1_0(double x, double y) { + return !(x < y) ? 1 : 0; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_gt_fixed_0_1(float x, float y) { + return !(x < y) ? 0 : 1; + } + @DontCompile + public static int golden_float_BoolTest_gt_fixed_0_1(float x, float y) { + return !(x < y) ? 0 : 1; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_gt_fixed_0_1(double x, double y) { + return !(x < y) ? 0 : 1; + } + @DontCompile + public static int golden_double_BoolTest_gt_fixed_0_1(double x, double y) { + return !(x < y) ? 0 : 1; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_gt_fixed_10_20(float x, float y) { + return !(x < y) ? 10 : 20; + } + @DontCompile + public static int golden_float_BoolTest_gt_fixed_10_20(float x, float y) { + return !(x < y) ? 10 : 20; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_gt_fixed_10_20(double x, double y) { + return !(x < y) ? 10 : 20; + } + @DontCompile + public static int golden_double_BoolTest_gt_fixed_10_20(double x, double y) { + return !(x < y) ? 10 : 20; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_gt_variable_results(float x, float y, int a, int b) { + return !(x < y) ? a : b; + } + @DontCompile + public static int golden_float_BoolTest_gt_variable_results(float x, float y, int a, int b) { + return !(x < y) ? a : b; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_gt_variable_results(double x, double y, int a, int b) { + return !(x < y) ? a : b; + } + @DontCompile + public static int golden_double_BoolTest_gt_variable_results(double x, double y, int a, int b) { + return !(x < y) ? a : b; + } + + @Run(test = {"test_float_BoolTest_gt_fixed_1_0", "test_double_BoolTest_gt_fixed_1_0", + "test_float_BoolTest_gt_fixed_0_1", "test_double_BoolTest_gt_fixed_0_1", + "test_float_BoolTest_gt_fixed_10_20", "test_double_BoolTest_gt_fixed_10_20", + "test_float_BoolTest_gt_variable_results", "test_double_BoolTest_gt_variable_results"}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_gt_fixed_1_0(x, y); + int expected = golden_float_BoolTest_gt_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Float failed (gt), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_gt_fixed_1_0(x, y); + int expected = golden_double_BoolTest_gt_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Double failed (gt), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_gt_fixed_0_1(x, y); + int expected = golden_float_BoolTest_gt_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Float failed (gt, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_gt_fixed_0_1(x, y); + int expected = golden_double_BoolTest_gt_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Double failed (gt, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_gt_fixed_10_20(x, y); + int expected = golden_float_BoolTest_gt_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Float failed (gt, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_gt_fixed_10_20(x, y); + int expected = golden_double_BoolTest_gt_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Double failed (gt, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + for (int m = 0; m < TestFPComparison2.INTS.length; m++) { + for (int n = 0; n < TestFPComparison2.INTS.length; n++) { + int a = TestFPComparison2.INTS[m]; + int b = TestFPComparison2.INTS[n]; + int actual = test_float_BoolTest_gt_variable_results(x, y, a, b); + int expected = golden_float_BoolTest_gt_variable_results(x, y, a, b); + if (actual != expected) { + System.out.println("Float failed (gt), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + for (int m = 0; m < TestFPComparison2.INTS.length; m++) { + for (int n = 0; n < TestFPComparison2.INTS.length; n++) { + int a = TestFPComparison2.INTS[m]; + int b = TestFPComparison2.INTS[n]; + int actual = test_double_BoolTest_gt_variable_results(x, y, a, b); + int expected = golden_double_BoolTest_gt_variable_results(x, y, a, b); + if (actual != expected) { + System.out.println("Double failed (gt), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} + +class Test_gt_2 { + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_gt_fixed_1_0(float x, float y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x <= y + // return 0 + // when neither is NaN, and x > y + return !(x > y) ? 1 : 0; + } + @DontCompile + public static int golden_float_BoolTest_gt_fixed_1_0(float x, float y) { + return !(x > y) ? 1 : 0; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_gt_fixed_1_0(double x, double y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x <= y + // return 0 + // when neither is NaN, and x > y + return !(x > y) ? 1 : 0; + } + @DontCompile + public static int golden_double_BoolTest_gt_fixed_1_0(double x, double y) { + return !(x > y) ? 1 : 0; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_gt_fixed_0_1(float x, float y) { + return !(x > y) ? 0 : 1; + } + @DontCompile + public static int golden_float_BoolTest_gt_fixed_0_1(float x, float y) { + return !(x > y) ? 0 : 1; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_gt_fixed_0_1(double x, double y) { + return !(x > y) ? 0 : 1; + } + @DontCompile + public static int golden_double_BoolTest_gt_fixed_0_1(double x, double y) { + return !(x > y) ? 0 : 1; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_gt_fixed_10_20(float x, float y) { + return !(x > y) ? 10 : 20; + } + @DontCompile + public static int golden_float_BoolTest_gt_fixed_10_20(float x, float y) { + return !(x > y) ? 10 : 20; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_gt_fixed_10_20(double x, double y) { + return !(x > y) ? 10 : 20; + } + @DontCompile + public static int golden_double_BoolTest_gt_fixed_10_20(double x, double y) { + return !(x > y) ? 10 : 20; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_float_BoolTest_gt_variable_results(float x, float y, int a, int b) { + return !(x > y) ? a : b; + } + @DontCompile + public static int golden_float_BoolTest_gt_variable_results(float x, float y, int a, int b) { + return !(x > y) ? a : b; + } + + @Test + @IR(counts = {IRNode.CMOVE_I, "1"}) + public static int test_double_BoolTest_gt_variable_results(double x, double y, int a, int b) { + return !(x > y) ? a : b; + } + @DontCompile + public static int golden_double_BoolTest_gt_variable_results(double x, double y, int a, int b) { + return !(x > y) ? a : b; + } + + @Run(test = {"test_float_BoolTest_gt_fixed_1_0", "test_double_BoolTest_gt_fixed_1_0", + "test_float_BoolTest_gt_fixed_0_1", "test_double_BoolTest_gt_fixed_0_1", + "test_float_BoolTest_gt_fixed_10_20", "test_double_BoolTest_gt_fixed_10_20", + "test_float_BoolTest_gt_variable_results", "test_double_BoolTest_gt_variable_results"}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_gt_fixed_1_0(x, y); + int expected = golden_float_BoolTest_gt_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Float failed (gt), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_gt_fixed_1_0(x, y); + int expected = golden_double_BoolTest_gt_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Double failed (gt), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_gt_fixed_0_1(x, y); + int expected = golden_float_BoolTest_gt_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Float failed (gt, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_gt_fixed_0_1(x, y); + int expected = golden_double_BoolTest_gt_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Double failed (gt, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + int actual = test_float_BoolTest_gt_fixed_10_20(x, y); + int expected = golden_float_BoolTest_gt_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Float failed (gt, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + int actual = test_double_BoolTest_gt_fixed_10_20(x, y); + int expected = golden_double_BoolTest_gt_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Double failed (gt, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + for (int m = 0; m < TestFPComparison2.INTS.length; m++) { + for (int n = 0; n < TestFPComparison2.INTS.length; n++) { + int a = TestFPComparison2.INTS[m]; + int b = TestFPComparison2.INTS[n]; + int actual = test_float_BoolTest_gt_variable_results(x, y, a, b); + int expected = golden_float_BoolTest_gt_variable_results(x, y, a, b); + if (actual != expected) { + System.out.println("Float failed (gt), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + for (int m = 0; m < TestFPComparison2.INTS.length; m++) { + for (int n = 0; n < TestFPComparison2.INTS.length; n++) { + int a = TestFPComparison2.INTS[m]; + int b = TestFPComparison2.INTS[n]; + int actual = test_double_BoolTest_gt_variable_results(x, y, a, b); + int expected = golden_double_BoolTest_gt_variable_results(x, y, a, b); + if (actual != expected) { + System.out.println("Double failed (gt), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} From 59460ff700e36f8dba5cb50ddc60f107d7d5ad7f Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 16 Jun 2025 15:20:48 +0000 Subject: [PATCH 069/213] 8359664: G1: Remove default arg for pretouch_workers of G1CollectedHeap::expand Reviewed-by: tschatzl --- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index b9e06d0a711..838e3b000e0 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -572,7 +572,7 @@ class G1CollectedHeap : public CollectedHeap { // Returns true if the heap was expanded by the requested amount; // false otherwise. // (Rounds up to a G1HeapRegion boundary.) - bool expand(size_t expand_bytes, WorkerThreads* pretouch_workers = nullptr, double* expand_time_ms = nullptr); + bool expand(size_t expand_bytes, WorkerThreads* pretouch_workers, double* expand_time_ms = nullptr); bool expand_single_region(uint node_index); // Returns the PLAB statistics for a given destination. From 9652ae9a8d48924a90d25e9daffcdb7f582ff503 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 16 Jun 2025 15:25:51 +0000 Subject: [PATCH 070/213] 8347114: JMXServiceURL should require an explicit protocol Reviewed-by: dfuchs, sspitsyn --- .../management/remote/JMXConnectorServer.java | 3 +- .../remote/JMXConnectorServerMBean.java | 3 +- .../management/remote/JMXServiceURL.java | 18 +++--- .../connection/JMXServiceURLProtocol.java | 58 +++++++++++++++++++ 4 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 test/jdk/javax/management/remote/mandatory/connection/JMXServiceURLProtocol.java diff --git a/src/java.management/share/classes/javax/management/remote/JMXConnectorServer.java b/src/java.management/share/classes/javax/management/remote/JMXConnectorServer.java index a643a27e3dc..05fd8df8f55 100644 --- a/src/java.management/share/classes/javax/management/remote/JMXConnectorServer.java +++ b/src/java.management/share/classes/javax/management/remote/JMXConnectorServer.java @@ -133,8 +133,7 @@ public String[] getConnectionIds() { * one new connection to this connector server.

    * *

    A given connector need not support the generation of client - * stubs. However, the connectors specified by the JMX Remote API do - * (JMXMP Connector and RMI Connector).

    + * stubs. The RMI Connector does so.

    * *

    The default implementation of this method uses {@link * #getAddress} and {@link JMXConnectorFactory} to generate the diff --git a/src/java.management/share/classes/javax/management/remote/JMXConnectorServerMBean.java b/src/java.management/share/classes/javax/management/remote/JMXConnectorServerMBean.java index fdc7fa5b3a1..4d8602bb81b 100644 --- a/src/java.management/share/classes/javax/management/remote/JMXConnectorServerMBean.java +++ b/src/java.management/share/classes/javax/management/remote/JMXConnectorServerMBean.java @@ -186,8 +186,7 @@ public interface JMXConnectorServerMBean { * one new connection to this connector server.

    * *

    A given connector need not support the generation of client - * stubs. However, the connectors specified by the JMX Remote API do - * (JMXMP Connector and RMI Connector).

    + * stubs. The RMI Connector does so.

    * * @param env client connection parameters of the same sort that * can be provided to {@link JMXConnector#connect(Map) diff --git a/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java b/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java index b6c2860b9cd..da47f7a1eda 100644 --- a/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java +++ b/src/java.management/share/classes/javax/management/remote/JMXServiceURL.java @@ -238,8 +238,8 @@ public JMXServiceURL(String serviceURL) throws MalformedURLException { * {@link #JMXServiceURL(String, String, int, String) * JMXServiceURL(protocol, host, port, null)}.

    * - * @param protocol the protocol part of the URL. If null, defaults - * to jmxmp. + * @param protocol the protocol part of the URL. Must be specified, + * there is no default. * * @param host the host part of the URL. If host is null and if * local host name can be resolved to an IP, then host defaults @@ -255,7 +255,7 @@ public JMXServiceURL(String serviceURL) throws MalformedURLException { * @exception MalformedURLException if one of the parts is * syntactically incorrect, or if host is null and it * is not possible to find the local host name, or if - * port is negative. + * port is negative, or if protocol is null. */ public JMXServiceURL(String protocol, String host, int port) throws MalformedURLException { @@ -265,8 +265,8 @@ public JMXServiceURL(String protocol, String host, int port) /** *

    Constructs a JMXServiceURL with the given parts. * - * @param protocol the protocol part of the URL. If null, defaults - * to jmxmp. + * @param protocol the protocol part of the URL. Must be specified, + * there is no default. * * @param host the host part of the URL. If host is null and if * local host name can be resolved to an IP, then host defaults @@ -285,14 +285,14 @@ public JMXServiceURL(String protocol, String host, int port) * @exception MalformedURLException if one of the parts is * syntactically incorrect, or if host is null and it * is not possible to find the local host name, or if - * port is negative. + * port is negative, or if protocol is null. */ public JMXServiceURL(String protocol, String host, int port, String urlPath) throws MalformedURLException { - if (protocol == null) - protocol = "jmxmp"; - + if (protocol == null) { + throw new MalformedURLException("Misssing protocol name"); + } if (host == null) { InetAddress local; try { diff --git a/test/jdk/javax/management/remote/mandatory/connection/JMXServiceURLProtocol.java b/test/jdk/javax/management/remote/mandatory/connection/JMXServiceURLProtocol.java new file mode 100644 index 00000000000..2db6be4efe4 --- /dev/null +++ b/test/jdk/javax/management/remote/mandatory/connection/JMXServiceURLProtocol.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8347114 + * @summary Test JMXServiceURL does not accept a null protocol + * + * @run main JMXServiceURLProtocol + */ + +import java.net.MalformedURLException; +import javax.management.remote.JMXServiceURL; + +public class JMXServiceURLProtocol { + + public static void main(String[] args) throws Exception { + + try { + JMXServiceURL u = new JMXServiceURL("service:jmx:://"); + String proto = u.getProtocol(); + System.out.println("JMXServiceURL(String) with null protocol gets: " + u + " protocol: " + proto); + throw new RuntimeException("JMXServiceURL created using null protocol: " + u); + } catch (MalformedURLException e) { + System.out.println("JMXServiceURL with null protocol causes expected: " + e); + } + + try { + JMXServiceURL u = new JMXServiceURL(null, "localhost", 1234); + String proto = u.getProtocol(); + System.out.println("JMXServiceURL(params) with null protocol gets: " + u + " protocol: " + proto); + throw new RuntimeException("JMXServiceURL created using null protocol: " + u); + } catch (MalformedURLException e) { + System.out.println("JMXServiceURL with null protocol causes expected: " + e); + } + + } +} From 6e390ef17cf4b6134d5d53ba4e3ae8281fedb3f3 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Mon, 16 Jun 2025 15:55:51 +0000 Subject: [PATCH 071/213] 8358690: Some initialization code asks for AOT cache status way too early Reviewed-by: asmehra, adinn --- src/hotspot/share/cds/cdsConfig.cpp | 14 ++- src/hotspot/share/cds/dynamicArchive.cpp | 2 +- src/hotspot/share/cds/filemap.cpp | 2 +- src/hotspot/share/cds/metaspaceShared.cpp | 5 +- src/hotspot/share/code/aotCodeCache.cpp | 103 ++++++++++++++------ src/hotspot/share/code/aotCodeCache.hpp | 19 ++-- src/hotspot/share/oops/compressedKlass.hpp | 2 +- src/hotspot/share/oops/trainingData.cpp | 4 +- src/hotspot/share/opto/compile.cpp | 2 +- src/hotspot/share/runtime/init.cpp | 20 ++-- src/hotspot/share/runtime/sharedRuntime.cpp | 1 + src/hotspot/share/runtime/sharedRuntime.hpp | 35 +++++-- src/hotspot/share/runtime/stubRoutines.cpp | 6 +- src/hotspot/share/runtime/stubRoutines.hpp | 2 +- 14 files changed, 144 insertions(+), 73 deletions(-) diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index b93238eca88..c19c0776465 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -30,6 +30,7 @@ #include "cds/heapShared.hpp" #include "classfile/classLoaderDataShared.hpp" #include "classfile/moduleEntry.hpp" +#include "code/aotCodeCache.hpp" #include "include/jvm_io.h" #include "logging/log.hpp" #include "memory/universe.hpp" @@ -705,24 +706,29 @@ bool CDSConfig::check_vm_args_consistency(bool patch_mod_javabase, bool mode_fla } void CDSConfig::setup_compiler_args() { - // AOT profiles are supported only in the JEP 483 workflow. - bool can_dump_profiles = AOTClassLinking && new_aot_flags_used(); + // AOT profiles and AOT-compiled code are supported only in the JEP 483 workflow. + bool can_dump_profile_and_compiled_code = AOTClassLinking && new_aot_flags_used(); - if (is_dumping_preimage_static_archive() && can_dump_profiles) { + if (is_dumping_preimage_static_archive() && can_dump_profile_and_compiled_code) { // JEP 483 workflow -- training FLAG_SET_ERGO_IF_DEFAULT(AOTRecordTraining, true); FLAG_SET_ERGO(AOTReplayTraining, false); - } else if (is_dumping_final_static_archive() && can_dump_profiles) { + AOTCodeCache::disable_caching(); // No AOT code generation during training run + } else if (is_dumping_final_static_archive() && can_dump_profile_and_compiled_code) { // JEP 483 workflow -- assembly FLAG_SET_ERGO(AOTRecordTraining, false); FLAG_SET_ERGO_IF_DEFAULT(AOTReplayTraining, true); + AOTCodeCache::enable_caching(); // Generate AOT code during assembly phase. + disable_dumping_aot_code(); // Don't dump AOT code until metadata and heap are dumped. } else if (is_using_archive() && new_aot_flags_used()) { // JEP 483 workflow -- production FLAG_SET_ERGO(AOTRecordTraining, false); FLAG_SET_ERGO_IF_DEFAULT(AOTReplayTraining, true); + AOTCodeCache::enable_caching(); } else { FLAG_SET_ERGO(AOTReplayTraining, false); FLAG_SET_ERGO(AOTRecordTraining, false); + AOTCodeCache::disable_caching(); } } diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index b1072dbce9b..c2c4d0bcae3 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -32,8 +32,8 @@ #include "cds/cds_globals.hpp" #include "cds/cdsConfig.hpp" #include "cds/dynamicArchive.hpp" -#include "cds/lambdaProxyClassDictionary.hpp" #include "cds/lambdaFormInvokers.hpp" +#include "cds/lambdaProxyClassDictionary.hpp" #include "cds/metaspaceShared.hpp" #include "cds/regeneratedClasses.hpp" #include "classfile/classLoader.hpp" diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 59df255fcf3..35b46099e1b 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -923,7 +923,7 @@ void FileMapInfo::write_region(int region, char* base, size_t size, " crc 0x%08x", region_name(region), region, size, p2i(requested_base), _file_offset, crc); } else { - aot_log_info(aot)("Shared file region (%s) %d: %8zu" + aot_log_info(aot)("Shared file region (%s) %d: %8zu" " bytes", region_name(region), region, size); } diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 233e64c5e3e..02f53feeed8 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -2014,10 +2014,7 @@ void MetaspaceShared::initialize_shared_spaces() { TrainingData::print_archived_training_data_on(tty); - if (AOTCodeCache::is_on_for_use()) { - tty->print_cr("\n\nAOT Code"); - AOTCodeCache::print_on(tty); - } + AOTCodeCache::print_on(tty); // collect shared symbols and strings CountSharedSymbols cl; diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp index d0692ee678b..cb318938819 100644 --- a/src/hotspot/share/code/aotCodeCache.cpp +++ b/src/hotspot/share/code/aotCodeCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,8 +74,7 @@ static void report_load_failure() { vm_exit_during_initialization("Unable to use AOT Code Cache.", nullptr); } log_info(aot, codecache, init)("Unable to use AOT Code Cache."); - AOTAdapterCaching = false; - AOTStubCaching = false; + AOTCodeCache::disable_caching(); } static void report_store_failure() { @@ -84,10 +83,30 @@ static void report_store_failure() { vm_abort(false); } log_info(aot, codecache, exit)("Unable to create AOT Code Cache."); - AOTAdapterCaching = false; - AOTStubCaching = false; + AOTCodeCache::disable_caching(); } +// The sequence of AOT code caching flags and parametters settings. +// +// 1. The initial AOT code caching flags setting is done +// during call to CDSConfig::check_vm_args_consistency(). +// +// 2. The earliest AOT code state check done in compilationPolicy_init() +// where we set number of compiler threads for AOT assembly phase. +// +// 3. We determine presence of AOT code in AOT Cache in +// MetaspaceShared::open_static_archive() which is calles +// after compilationPolicy_init() but before codeCache_init(). +// +// 4. AOTCodeCache::initialize() is called during universe_init() +// and does final AOT state and flags settings. +// +// 5. Finally AOTCodeCache::init2() is called after universe_init() +// when all GC settings are finalized. + +// Next methods determine which action we do with AOT code depending +// on phase of AOT process: assembly or production. + bool AOTCodeCache::is_dumping_adapter() { return AOTAdapterCaching && is_on_for_dump(); } @@ -104,6 +123,23 @@ bool AOTCodeCache::is_using_stub() { return AOTStubCaching && is_on_for_use(); } +// Next methods could be called regardless AOT code cache status. +// Initially they are called during flags parsing and finilized +// in AOTCodeCache::initialize(). +void AOTCodeCache::enable_caching() { + FLAG_SET_ERGO_IF_DEFAULT(AOTStubCaching, true); + FLAG_SET_ERGO_IF_DEFAULT(AOTAdapterCaching, true); +} + +void AOTCodeCache::disable_caching() { + FLAG_SET_ERGO(AOTStubCaching, false); + FLAG_SET_ERGO(AOTAdapterCaching, false); +} + +bool AOTCodeCache::is_caching_enabled() { + return AOTStubCaching || AOTAdapterCaching; +} + static uint32_t encode_id(AOTCodeEntry::Kind kind, int id) { assert(AOTCodeEntry::is_valid_entry_kind(kind), "invalid AOTCodeEntry kind %d", (int)kind); // There can be a conflict of id between an Adapter and *Blob, but that should not cause any functional issue @@ -125,19 +161,19 @@ uint AOTCodeCache::max_aot_code_size() { return _max_aot_code_size; } -// This method is called during universe_init() -// and does final AOT state and flags settings. +// It is called from MetaspaceShared::initialize_shared_spaces() +// which is called from universe_init(). +// At this point all AOT class linking seetings are finilized +// and AOT cache is open so we can map AOT code region. void AOTCodeCache::initialize() { #if defined(ZERO) || !(defined(AMD64) || defined(AARCH64)) log_info(aot, codecache, init)("AOT Code Cache is not supported on this platform."); - AOTAdapterCaching = false; - AOTStubCaching = false; + disable_caching(); return; #else if (FLAG_IS_DEFAULT(AOTCache)) { log_info(aot, codecache, init)("AOT Code Cache is not used: AOTCache is not specified."); - AOTAdapterCaching = false; - AOTStubCaching = false; + disable_caching(); return; // AOTCache must be specified to dump and use AOT code } @@ -158,18 +194,19 @@ void AOTCodeCache::initialize() { bool is_dumping = false; bool is_using = false; if (CDSConfig::is_dumping_final_static_archive() && CDSConfig::is_dumping_aot_linked_classes()) { - FLAG_SET_ERGO_IF_DEFAULT(AOTAdapterCaching, true); - FLAG_SET_ERGO_IF_DEFAULT(AOTStubCaching, true); is_dumping = true; + enable_caching(); + is_dumping = is_caching_enabled(); } else if (CDSConfig::is_using_archive() && CDSConfig::is_using_aot_linked_classes()) { - FLAG_SET_ERGO_IF_DEFAULT(AOTAdapterCaching, true); - FLAG_SET_ERGO_IF_DEFAULT(AOTStubCaching, true); - is_using = true; + enable_caching(); + is_using = is_caching_enabled(); } else { log_info(aot, codecache, init)("AOT Code Cache is not used: AOT Class Linking is not used."); + disable_caching(); return; // nothing to do } - if (!AOTAdapterCaching && !AOTStubCaching) { + if (!(is_dumping || is_using)) { + disable_caching(); return; // AOT code caching disabled on command line } _max_aot_code_size = AOTCodeMaxSize; @@ -182,6 +219,7 @@ void AOTCodeCache::initialize() { size_t aot_code_size = is_using ? AOTCacheAccess::get_aot_code_region_size() : 0; if (is_using && aot_code_size == 0) { log_info(aot, codecache, init)("AOT Code Cache is empty"); + disable_caching(); return; } if (!open_cache(is_dumping, is_using)) { @@ -201,10 +239,11 @@ void AOTCodeCache::initialize() { static AOTCodeCache* opened_cache = nullptr; // Use this until we verify the cache AOTCodeCache* AOTCodeCache::_cache = nullptr; +DEBUG_ONLY( bool AOTCodeCache::_passed_init2 = false; ) -// This method is called after universe_init() -// when all GC settings are finalized. +// It is called after universe_init() when all GC settings are finalized. void AOTCodeCache::init2() { + DEBUG_ONLY( _passed_init2 = true; ) if (opened_cache == nullptr) { return; } @@ -220,7 +259,6 @@ void AOTCodeCache::init2() { AOTCodeAddressTable* table = opened_cache->_table; assert(table != nullptr, "should be initialized already"); table->init_extrs(); - table->init_early_stubs(); // Now cache and address table are ready for AOT code generation _cache = opened_cache; @@ -312,6 +350,13 @@ AOTCodeCache::AOTCodeCache(bool is_dumping, bool is_using) : _table = new AOTCodeAddressTable(); } +void AOTCodeCache::init_early_stubs_table() { + AOTCodeAddressTable* table = addr_table(); + if (table != nullptr) { + table->init_early_stubs(); + } +} + void AOTCodeCache::init_shared_blobs_table() { AOTCodeAddressTable* table = addr_table(); if (table != nullptr) { @@ -1691,11 +1736,13 @@ int AOTCodeAddressTable::id_for_address(address addr, RelocIterator reloc, CodeB return id; } +// This is called after initialize() but before init2() +// and _cache is not set yet. void AOTCodeCache::print_on(outputStream* st) { - AOTCodeCache* cache = open_for_use(); - if (cache != nullptr) { - uint count = cache->_load_header->entries_count(); - uint* search_entries = (uint*)cache->addr(cache->_load_header->entries_offset()); // [id, index] + if (opened_cache != nullptr && opened_cache->for_use()) { + st->print_cr("\nAOT Code Cache"); + uint count = opened_cache->_load_header->entries_count(); + uint* search_entries = (uint*)opened_cache->addr(opened_cache->_load_header->entries_offset()); // [id, index] AOTCodeEntry* load_entries = (AOTCodeEntry*)(search_entries + 2 * count); for (uint i = 0; i < count; i++) { @@ -1705,12 +1752,10 @@ void AOTCodeCache::print_on(outputStream* st) { uint entry_position = entry->offset(); uint name_offset = entry->name_offset() + entry_position; - const char* saved_name = cache->addr(name_offset); + const char* saved_name = opened_cache->addr(name_offset); - st->print_cr("%4u: entry_idx:%4u Kind:%u Id:%u size=%u '%s'", - i, index, entry->kind(), entry->id(), entry->size(), saved_name); + st->print_cr("%4u: %10s idx:%4u Id:%u size=%u '%s'", + i, aot_code_entry_kind_name[entry->kind()], index, entry->id(), entry->size(), saved_name); } - } else { - st->print_cr("failed to map code cache"); } } diff --git a/src/hotspot/share/code/aotCodeCache.hpp b/src/hotspot/share/code/aotCodeCache.hpp index e7b056ac974..1595f19e905 100644 --- a/src/hotspot/share/code/aotCodeCache.hpp +++ b/src/hotspot/share/code/aotCodeCache.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -297,6 +297,7 @@ class AOTCodeCache : public CHeapObj { void load_strings(); int store_strings(); + static void init_early_stubs_table() NOT_CDS_RETURN; static void init_shared_blobs_table() NOT_CDS_RETURN; static void init_early_c1_table() NOT_CDS_RETURN; @@ -346,7 +347,8 @@ class AOTCodeCache : public CHeapObj { // Static access private: - static AOTCodeCache* _cache; + static AOTCodeCache* _cache; + DEBUG_ONLY( static bool _passed_init2; ) static bool open_cache(bool is_dumping, bool is_using); bool verify_config() { @@ -356,19 +358,20 @@ class AOTCodeCache : public CHeapObj { return true; } public: - static AOTCodeCache* cache() { return _cache; } + static AOTCodeCache* cache() { assert(_passed_init2, "Too early to ask"); return _cache; } static void initialize() NOT_CDS_RETURN; static void init2() NOT_CDS_RETURN; static void close() NOT_CDS_RETURN; - static bool is_on() CDS_ONLY({ return _cache != nullptr && !_cache->closing(); }) NOT_CDS_RETURN_(false); + static bool is_on() CDS_ONLY({ return cache() != nullptr && !_cache->closing(); }) NOT_CDS_RETURN_(false); static bool is_on_for_use() { return is_on() && _cache->for_use(); } static bool is_on_for_dump() { return is_on() && _cache->for_dump(); } - - static bool is_dumping_adapter() NOT_CDS_RETURN_(false); - static bool is_using_adapter() NOT_CDS_RETURN_(false); - static bool is_dumping_stub() NOT_CDS_RETURN_(false); + static bool is_dumping_adapter() NOT_CDS_RETURN_(false); static bool is_using_stub() NOT_CDS_RETURN_(false); + static bool is_using_adapter() NOT_CDS_RETURN_(false); + static void enable_caching() NOT_CDS_RETURN; + static void disable_caching() NOT_CDS_RETURN; + static bool is_caching_enabled() NOT_CDS_RETURN_(false); static const char* add_C_string(const char* str) NOT_CDS_RETURN_(str); diff --git a/src/hotspot/share/oops/compressedKlass.hpp b/src/hotspot/share/oops/compressedKlass.hpp index 8666d4409e8..a8d79ab838e 100644 --- a/src/hotspot/share/oops/compressedKlass.hpp +++ b/src/hotspot/share/oops/compressedKlass.hpp @@ -214,7 +214,7 @@ class CompressedKlassPointers : public AllStatic { // Can only be used after initialization static address base() { check_init(_base); return _base; } - static address base_addr() { return (address)&_base; } + static address base_addr() { return (address)&_base; } static int shift() { check_init(_shift); return _shift; } static address klass_range_start() { return _klass_range_start; } diff --git a/src/hotspot/share/oops/trainingData.cpp b/src/hotspot/share/oops/trainingData.cpp index 2ae1ac18699..cc15fe944f2 100644 --- a/src/hotspot/share/oops/trainingData.cpp +++ b/src/hotspot/share/oops/trainingData.cpp @@ -220,8 +220,8 @@ CompileTrainingData* CompileTrainingData::make(CompileTask* task) { last_ctd = ctd; } } else { - last_ctd = ctd; - mtd->notice_toplevel_compilation(level); + last_ctd = ctd; + mtd->notice_toplevel_compilation(level); } } return ctd; diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index fb42ba4c9af..d256b7a7d5e 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -4551,7 +4551,7 @@ void Compile::dump_print_inlining() { void Compile::log_late_inline(CallGenerator* cg) { if (log() != nullptr) { - log()->head("late_inline method='%d' inline_id='" JLONG_FORMAT "'", log()->identify(cg->method()), + log()->head("late_inline method='%d' inline_id='" JLONG_FORMAT "'", log()->identify(cg->method()), cg->unique_id()); JVMState* p = cg->call_node()->jvms(); while (p != nullptr) { diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp index dbd0a355efe..b54afd9f735 100644 --- a/src/hotspot/share/runtime/init.cpp +++ b/src/hotspot/share/runtime/init.cpp @@ -71,7 +71,7 @@ void icache_init2(); void preuniverse_stubs_init(); void initial_stubs_init(); -jint universe_init(); // depends on codeCache_init and initial_stubs_init +jint universe_init(); // depends on codeCache_init and preuniverse_stubs_init // depends on universe_init, must be before interpreter_init (currently only on SPARC) void gc_barrier_stubs_init(); void continuations_init(); // depends on flags (UseCompressedOops) and barrier sets @@ -132,15 +132,10 @@ jint init_globals() { icache_init2(); // depends on VM_Version for choosing the mechanism // initialize stubs needed before we can init the universe preuniverse_stubs_init(); - // stub routines in initial blob are referenced by later generated code - initial_stubs_init(); - // stack overflow exception blob is referenced by the interpreter - SharedRuntime::generate_initial_stubs(); - jint status = universe_init(); // dependent on codeCache_init and - // initial_stubs_init and metaspace_init. - if (status != JNI_OK) + jint status = universe_init(); // dependent on codeCache_init and preuniverse_stubs_init + if (status != JNI_OK) { return status; - + } #ifdef LEAK_SANITIZER { // Register the Java heap with LSan. @@ -148,8 +143,13 @@ jint init_globals() { LSAN_REGISTER_ROOT_REGION(summary.start(), summary.reserved_size()); } #endif // LEAK_SANITIZER - AOTCodeCache::init2(); // depends on universe_init + AOTCodeCache::init2(); // depends on universe_init, must be before initial_stubs_init AsyncLogWriter::initialize(); + + initial_stubs_init(); // initial stub routines + // stack overflow exception blob is referenced by the interpreter + SharedRuntime::generate_initial_stubs(); + AOTCodeCache::init_early_stubs_table(); // need this after initial_stubs gc_barrier_stubs_init(); // depends on universe_init, must be before interpreter_init continuations_init(); // must precede continuation stub generation continuation_stubs_init(); // depends on continuations_init diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 9c710fc98e4..9664084a2f2 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -570,6 +570,7 @@ address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* curr if (StubRoutines::returns_to_call_stub(return_address)) { // The deferred StackWatermarkSet::after_unwind check will be performed in // JavaCallWrapper::~JavaCallWrapper + assert (StubRoutines::catch_exception_entry() != nullptr, "must be generated before"); return StubRoutines::catch_exception_entry(); } if (blob != nullptr && blob->is_upcall_stub()) { diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index eb2ffb82e5a..be391c3b0d5 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -288,15 +288,36 @@ class SharedRuntime: AllStatic { } // Implicit exceptions - static address throw_AbstractMethodError_entry() { return _throw_AbstractMethodError_blob->entry_point(); } - static address throw_IncompatibleClassChangeError_entry() { return _throw_IncompatibleClassChangeError_blob->entry_point(); } - static address throw_NullPointerException_at_call_entry() { return _throw_NullPointerException_at_call_blob->entry_point(); } - static address throw_StackOverflowError_entry() { return _throw_StackOverflowError_blob->entry_point(); } - static address throw_delayed_StackOverflowError_entry() { return _throw_delayed_StackOverflowError_blob->entry_point(); } + static address throw_AbstractMethodError_entry() { + assert(_throw_AbstractMethodError_blob != nullptr, ""); + return _throw_AbstractMethodError_blob->entry_point(); + } + static address throw_IncompatibleClassChangeError_entry() { + assert(_throw_IncompatibleClassChangeError_blob != nullptr, ""); + return _throw_IncompatibleClassChangeError_blob->entry_point(); + } + static address throw_NullPointerException_at_call_entry() { + assert(_throw_NullPointerException_at_call_blob != nullptr, ""); + return _throw_NullPointerException_at_call_blob->entry_point(); + } + static address throw_StackOverflowError_entry() { + assert(_throw_StackOverflowError_blob != nullptr, ""); + return _throw_StackOverflowError_blob->entry_point(); + } + static address throw_delayed_StackOverflowError_entry() { + assert(_throw_delayed_StackOverflowError_blob != nullptr, ""); + return _throw_delayed_StackOverflowError_blob->entry_point(); + } #if INCLUDE_JFR - static address jfr_write_checkpoint() { return _jfr_write_checkpoint_blob->entry_point(); } - static address jfr_return_lease() { return _jfr_return_lease_blob->entry_point(); } + static address jfr_write_checkpoint() { + assert(_jfr_write_checkpoint_blob != nullptr, ""); + return _jfr_write_checkpoint_blob->entry_point(); + } + static address jfr_return_lease() { + assert(_jfr_return_lease_blob != nullptr, ""); + return _jfr_return_lease_blob->entry_point(); + } #endif // Counters diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index 163ab4bfb6a..256d51bf5c2 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -181,10 +181,6 @@ StubGenBlobId StubRoutines::stub_to_blob(StubGenStubId stubId) { #endif // ASSERT // Initialization -// -// Note: to break cycle with universe initialization, stubs are generated in two phases. -// The first one generates stubs needed during universe init (e.g., _handle_must_compile_first_entry). -// The second phase includes all other stubs (which may depend on universe being initialized.) extern void StubGenerator_generate(CodeBuffer* code, StubGenBlobId blob_id); // only interface to generators @@ -194,6 +190,7 @@ void UnsafeMemoryAccess::create_table(int max_size) { } bool UnsafeMemoryAccess::contains_pc(address pc) { + assert(UnsafeMemoryAccess::_table != nullptr, ""); for (int i = 0; i < UnsafeMemoryAccess::_table_length; i++) { UnsafeMemoryAccess* entry = &UnsafeMemoryAccess::_table[i]; if (pc >= entry->start_pc() && pc < entry->end_pc()) { @@ -204,6 +201,7 @@ bool UnsafeMemoryAccess::contains_pc(address pc) { } address UnsafeMemoryAccess::page_error_continue_pc(address pc) { + assert(UnsafeMemoryAccess::_table != nullptr, ""); for (int i = 0; i < UnsafeMemoryAccess::_table_length; i++) { UnsafeMemoryAccess* entry = &UnsafeMemoryAccess::_table[i]; if (pc >= entry->start_pc() && pc < entry->end_pc()) { diff --git a/src/hotspot/share/runtime/stubRoutines.hpp b/src/hotspot/share/runtime/stubRoutines.hpp index 7548a97ced8..bd60b931f0c 100644 --- a/src/hotspot/share/runtime/stubRoutines.hpp +++ b/src/hotspot/share/runtime/stubRoutines.hpp @@ -339,7 +339,7 @@ class StubRoutines: AllStatic { // a subroutine for debugging the GC static address verify_oop_subroutine_entry_address() { return (address)&_verify_oop_subroutine_entry; } - static CallStub call_stub() { return CAST_TO_FN_PTR(CallStub, _call_stub_entry); } + static CallStub call_stub() { assert(_call_stub_entry != nullptr, ""); return CAST_TO_FN_PTR(CallStub, _call_stub_entry); } static address select_arraycopy_function(BasicType t, bool aligned, bool disjoint, const char* &name, bool dest_uninitialized); From 06d804a0f004f9403c7c12e1a9f2ca8775c639f7 Mon Sep 17 00:00:00 2001 From: Stuart Marks Date: Mon, 16 Jun 2025 15:56:08 +0000 Subject: [PATCH 072/213] 8338140: (str) Add notes to String.trim and String.isEmpty pointing to newer APIs Reviewed-by: naoto, bpb --- .../share/classes/java/lang/String.java | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 76566de089c..52af7dfd503 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -1589,6 +1589,11 @@ public int length() { * @return {@code true} if {@link #length()} is {@code 0}, otherwise * {@code false} * + * @apiNote + * To determine whether a string contains only + * {@linkplain Character#isWhitespace(int) white space}, use + * {@link #isBlank() isBlank}. + * * @since 1.6 */ @Override @@ -3827,9 +3832,13 @@ public String toUpperCase() { * begins with the character at index k and ends with the * character at index m-that is, the result of * {@code this.substring(k, m + 1)}. - *

    - * This method may be used to trim space (as defined above) from - * the beginning and end of a string. + * + * @apiNote + * This method removes leading and trailing space characters and ASCII control + * characters from the string. To remove characters using a Unicode-based definition of + * {@linkplain Character#isWhitespace(int) white space}, use {@link #strip() strip}, + * {@link #stripIndent() stripIndent}, {@link #stripLeading() stripLeading}, or + * {@link #stripTrailing() stripTrailing}. * * @return a string whose value is this string, with all leading * and trailing space removed, or this string if it @@ -3934,13 +3943,9 @@ public String stripTrailing() { } /** - * Returns {@code true} if the string is empty or contains only - * {@linkplain Character#isWhitespace(int) white space} codepoints, - * otherwise {@code false}. - * - * @return {@code true} if the string is empty or contains only - * {@linkplain Character#isWhitespace(int) white space} codepoints, - * otherwise {@code false} + * {@return {@code true} if the string is {@linkplain #isEmpty empty} or contains + * only {@linkplain Character#isWhitespace(int) white space} codepoints, + * otherwise {@code false}} * * @see Character#isWhitespace(int) * From 2f2acb2e3f292517456f5b328a35182863188653 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 16 Jun 2025 16:10:59 +0000 Subject: [PATCH 073/213] 8359593: JFR: Instrumentation of java.lang.String corrupts recording Reviewed-by: mgronlun --- .../jdk/jfr/internal/tracing/ExcludeList.java | 32 +++--- .../jfr/event/tracing/TestTracedString.java | 97 +++++++++++++++++++ 2 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 test/jdk/jdk/jfr/event/tracing/TestTracedString.java diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/ExcludeList.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/ExcludeList.java index 8aa889dd68d..58408da811e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/ExcludeList.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/ExcludeList.java @@ -24,38 +24,46 @@ */ package jdk.jfr.internal.tracing; +import java.util.Set; + // // The JVM will skip all classes in the jdk.jfr module, so it's not added here. public final class ExcludeList { private static final String[] EXCLUDED_CLASSES = { // Used by MethodTiming event to accumulate invocations. "java/util/concurrent/atomic/AtomicLong", - // Used by EventWriter + // Used by EventWriter, directly or indirectly. "sun/misc/Unsafe", - "jdk/internal/misc/Unsafe;", + "jdk/internal/misc/Unsafe", + "java/lang/StringLatin1", + "java/lang/StringUTF16", }; private static final String[] EXCLUDED_PREFIX = { // Used by MethodTiming event to store invocations, including inner classes. "java/util/concurrent/ConcurrentHashMap", // Can't trigger of these classes during PlatformTracer::onMethodTrace(...) - "jdk/internal/", // jdk/internal/classfile, jdk/internal/loader and jdk/internal/foreign + // Also to avoid recursion with EventWriter::putString + "jdk/internal/", // jdk/internal/classfile, // jdk/internal/vm, jdk/internal/util, jdk/internal/loader and jdk/internal/foreign "java/lang/classfile/" }; - private static final String[] EXCLUDED_METHODS = { + private static final Set EXCLUDED_METHODS = Set.of( // Long used by MethodTiming event when looking up entry for timing entry "java.lang.Long::", "java.lang.Long::valueOf", - "java.lang.Number::" - }; + "java.lang.Number::", + // Used by EventWriter::putString, directly or indirectly. + "java.lang.String::charAt", + "java.lang.String::length", + "java.lang.String::coder", // Used by charAt(int) + "java.lang.String::checkIndex", // Used by charAt(int) + "java.lang.String::isLatin1", // Used by charAt() + "java.lang.String::equals", // Used by StringPool + "java.lang.String::hashCode" // Used by StringPool + ); public static boolean containsMethod(String methodName) { - for (String method : EXCLUDED_METHODS) { - if (method.equals(methodName)) { - return true; - } - } - return false; + return EXCLUDED_METHODS.contains(methodName); } public static boolean containsClass(String className) { diff --git a/test/jdk/jdk/jfr/event/tracing/TestTracedString.java b/test/jdk/jdk/jfr/event/tracing/TestTracedString.java new file mode 100644 index 00000000000..d4bf84010eb --- /dev/null +++ b/test/jdk/jdk/jfr/event/tracing/TestTracedString.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.event.tracing; + +import java.nio.file.Path; + +import jdk.jfr.Configuration; +import jdk.jfr.Name; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingFile; + +/** + * @test + * @summary Tests that java.lang.String can be traced. + * @requires vm.flagless + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm jdk.jfr.event.tracing.TestTracedString + **/ +public class TestTracedString { + private static long SEED = System.currentTimeMillis(); + + @Name("Message") + static class MessageEvent extends jdk.jfr.Event { + String message; + long checkSum; + } + + public static void main(String[] args) throws Exception { + Configuration c = Configuration.getConfiguration("default"); + Path file = Path.of("recording.jfr"); + try (Recording r = new Recording(c)) { + r.enable("jdk.MethodTrace").with("filter", "java.lang.String"); + r.start(); + emit(100, ""); + emit(100, "short"); + emit(100, "medium medium medium medium medium medium 1"); + emit(100, "medium medium medium medium medium medium 2"); + emit(100, "long".repeat(100)); + r.stop(); + r.dump(file); + int count = 0; + for (RecordedEvent e : RecordingFile.readAllEvents(file)) { + if (e.getEventType().getName().equals("Message")) { + String text = e.getString("message"); + long checkSum = e.getLong("checkSum"); + if (checkSum(text) != checkSum) { + throw new Exception("Incorrect checksum for text " + text); + } + count++; + } + } + if (count != 500) { + throw new Exception("Expected 500 Message events. Got " + count); + } + } + } + + private static void emit(int count, String text) { + long checkSum = checkSum(text); + for (int i = 0; i < count; i++) { + MessageEvent m = new MessageEvent(); + m.message = text; + m.checkSum = checkSum; + m.commit(); + } + } + + private static long checkSum(String text) { + long checkSum = SEED; + for (int i = 0; i < text.length(); i++) { + checkSum += 17 * text.charAt(i); + } + return checkSum; + } +} From e57a214e2a1059109dd028369d518298cfa5d5b4 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 16 Jun 2025 16:52:17 +0000 Subject: [PATCH 074/213] 8359242: JFR: Missing help text for method trace and timing Reviewed-by: mgronlun --- .../jfr/internal/jfc/model/XmlElement.java | 9 ++++++- .../jdk/jfr/internal/jfc/model/XmlText.java | 26 ++++++++++++++++--- .../jfr/internal/settings/MethodSetting.java | 4 ++- .../jdk/jfr/internal/tracing/Filter.java | 6 ++++- .../jfr/internal/tracing/PlatformTracer.java | 4 --- src/jdk.jfr/share/conf/jfr/default.jfc | 6 +++-- src/jdk.jfr/share/conf/jfr/profile.jfc | 6 +++-- 7 files changed, 46 insertions(+), 15 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlElement.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlElement.java index d05516ed229..e2d40a635aa 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlElement.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,6 +107,13 @@ final String getContent() { return content; } + final String getContentOrEmptyQuote() { + if (content == null || content.isEmpty()) { + return "\"\""; + } + return content; + } + final void addListener(XmlElement listener) { listeners.add(listener); listener.addProducer(this); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlText.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlText.java index 4d90dd3c51c..9eedf59d4bc 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlText.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/jfc/model/XmlText.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,8 @@ */ package jdk.jfr.internal.jfc.model; +import jdk.jfr.internal.tracing.Filter; + // Corresponds to final class XmlText extends XmlInput { @@ -35,7 +37,7 @@ public String getOptionSyntax() { sb.append(getContentType().orElse("text")); sb.append(">"); sb.append(" ("); - String content = getContent(); + String content = getContentOrEmptyQuote(); if (isTimespan()) { // "20 ms" becomes "20ms" content = content.replaceAll("\\s", ""); @@ -57,7 +59,7 @@ public void configure(String value) { @Override public void configure(UserInterface ui) throws AbortException { ui.println(); - ui.println(getLabel() + ": " + getContent() + " (default)"); + ui.println(getLabel() + ": " + getContentOrEmptyQuote() + " (default)"); while (!readInput(ui)) { ; } @@ -71,9 +73,21 @@ protected Result evaluate() { private boolean readInput(UserInterface ui) throws AbortException { String line = ui.readLine(); if (line.isBlank()) { - ui.println("Using default: " + getContent()); + ui.println("Using default: " + getContentOrEmptyQuote()); return true; } + if (isMethodFilter()) { + if (!Filter.isValid(line)) { + ui.println(""" + Not a valid method filter. A filter can be an annotation \ + (@jakarta.ws.rs.GET), a full qualified class name (com.example.Foo), \ + a fully qualified method reference (java.lang.HashMap::resize) or a \ + class initializer (::). Use for constructors. \ + Separate multiple filters with semicolon.\ + """); + return false; + } + } if (isTimespan()) { try { line = Utilities.parseTimespan(line); @@ -90,4 +104,8 @@ private boolean readInput(UserInterface ui) throws AbortException { private boolean isTimespan() { return getContentType().orElse("text").equals("timespan"); } + + private boolean isMethodFilter() { + return getContentType().orElse("text").equals("method-filter"); + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java index f4f3d93c01c..f3e1069ca21 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java @@ -33,6 +33,7 @@ import jdk.jfr.internal.PlatformEventType; import jdk.jfr.internal.Type; import jdk.jfr.internal.tracing.Modification; +import jdk.jfr.internal.tracing.Filter; import jdk.jfr.internal.tracing.PlatformTracer; @MetadataDefinition @@ -47,8 +48,9 @@ public MethodSetting(PlatformEventType eventType, Modification modification, Str this.modification = modification; } + @Override public boolean isValid(String text) { - return PlatformTracer.isValidFilter(text); + return Filter.isValid(text); } @Override diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/Filter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/Filter.java index 782cc3e56d1..177b6d03166 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/Filter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/Filter.java @@ -30,7 +30,11 @@ * Class that represents the filter a user can specify for the MethodTrace and * MethodTiming event. */ -record Filter(String className, String methodName, String annotationName, Modification modification) { +public record Filter(String className, String methodName, String annotationName, Modification modification) { + + public static boolean isValid(String filter) { + return of(filter, Modification.NONE) != null; + } static Filter of(String filter, Modification modification) { if (filter.startsWith("@")) { diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java index abc3b0f8cd0..5985b28b58e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java @@ -158,10 +158,6 @@ public static void addTiming(long id, long duration) { } } - public static boolean isValidFilter(String text) { - return Filter.of(text, null) != null; - } - public static void setFilters(Modification modification, List filters) { ensureInitialized(); publishClasses(applyFilter(modification, filters)); diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc index 565dfbdee05..20051864895 100644 --- a/src/jdk.jfr/share/conf/jfr/default.jfc +++ b/src/jdk.jfr/share/conf/jfr/default.jfc @@ -1189,9 +1189,11 @@ 20 ms - + - + false diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc index 2c0812e75fe..5ffdc8d9e4d 100644 --- a/src/jdk.jfr/share/conf/jfr/profile.jfc +++ b/src/jdk.jfr/share/conf/jfr/profile.jfc @@ -1188,9 +1188,11 @@ 10 ms - + - + false From 9a1c1f2efb1367ea8196b56d1b9b3b0841e4398d Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Mon, 16 Jun 2025 17:56:27 +0000 Subject: [PATCH 075/213] 8357847: (ch) AsynchronousFileChannel implementations should support FFM Buffers Reviewed-by: alanb --- .../ch/SimpleAsynchronousFileChannelImpl.java | 8 +++- .../WindowsAsynchronousFileChannelImpl.java | 48 +++++++++++-------- .../AsynchronousFileChannel/Basic.java | 16 +++++-- .../java/nio/channels/etc/MemorySegments.java | 7 +-- 4 files changed, 47 insertions(+), 32 deletions(-) diff --git a/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java index 440c254601d..13de40e9a24 100644 --- a/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SimpleAsynchronousFileChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -327,6 +327,8 @@ Future implRead(final ByteBuffer dst, return null; } + IOUtil.acquireScope(dst, true); + final PendingFuture result = (handler == null) ? new PendingFuture(this) : null; Runnable task = new Runnable() { @@ -349,6 +351,7 @@ public void run() { } finally { end(); threads.remove(ti); + IOUtil.releaseScope(dst); } if (handler == null) { result.setResult(n, exc); @@ -381,6 +384,8 @@ Future implWrite(final ByteBuffer src, return null; } + IOUtil.acquireScope(src, true); + final PendingFuture result = (handler == null) ? new PendingFuture(this) : null; Runnable task = new Runnable() { @@ -403,6 +408,7 @@ public void run() { } finally { end(); threads.remove(ti); + IOUtil.releaseScope(src); } if (handler == null) { result.setResult(n, exc); diff --git a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java index e3f65f82f0c..5df8aef7431 100644 --- a/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java +++ b/src/java.base/windows/classes/sun/nio/ch/WindowsAsynchronousFileChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -410,8 +410,10 @@ private class ReadTask implements Runnable, Iocp.ResultHandler { this.result = result; } - void releaseBufferIfSubstituted() { - if (buf != dst && RELEASED.compareAndSet(this, false, true)) { + void releaseScopeOrCacheSubstitute() { + if (buf == dst) { + IOUtil.releaseScope(dst); + } else if (RELEASED.compareAndSet(this, false, true)) { Util.releaseTemporaryDirectBuffer(buf); } } @@ -444,12 +446,13 @@ public void run() { long address; // Substitute a native buffer if not direct - if (dst instanceof DirectBuffer) { + if (dst.isDirect()) { buf = dst; - address = ((DirectBuffer)dst).address() + pos; + IOUtil.acquireScope(dst, true); + address = IOUtil.bufferAddress(dst) + pos; } else { buf = Util.getTemporaryDirectBuffer(rem); - address = ((DirectBuffer)buf).address(); + address = IOUtil.bufferAddress(buf) + pos; } boolean pending = false; @@ -479,7 +482,7 @@ public void run() { } finally { if (!pending) // release resources - releaseBufferIfSubstituted(); + releaseScopeOrCacheSubstitute(); end(); } @@ -494,8 +497,8 @@ public void run() { public void completed(int bytesTransferred, boolean canInvokeDirect) { updatePosition(bytesTransferred); - // return direct buffer to cache if substituted - releaseBufferIfSubstituted(); + // release direct buffer scope or return substitute to cache + releaseScopeOrCacheSubstitute(); // release waiters and invoke completion handler result.setResult(bytesTransferred); @@ -512,8 +515,8 @@ public void failed(int error, IOException x) { if (error == ERROR_HANDLE_EOF) { completed(-1, false); } else { - // return direct buffer to cache if substituted - releaseBufferIfSubstituted(); + // release direct buffer scope or return substitute to cache + releaseScopeOrCacheSubstitute(); // release waiters if (isOpen()) { @@ -600,8 +603,10 @@ private class WriteTask implements Runnable, Iocp.ResultHandler { this.result = result; } - void releaseBufferIfSubstituted() { - if (buf != src && RELEASED.compareAndSet(this, false, true)) { + void releaseScopeOrCacheSubstitute() { + if (buf == src) { + IOUtil.releaseScope(src); + } else if (RELEASED.compareAndSet(this, false, true)) { Util.releaseTemporaryDirectBuffer(buf); } } @@ -624,9 +629,10 @@ public void run() { long address; // Substitute a native buffer if not direct - if (src instanceof DirectBuffer) { + if (src.isDirect()) { buf = src; - address = ((DirectBuffer)src).address() + pos; + IOUtil.acquireScope(src, true); + address = IOUtil.bufferAddress(src) + pos; } else { buf = Util.getTemporaryDirectBuffer(rem); buf.put(src); @@ -634,7 +640,7 @@ public void run() { // temporarily restore position as we don't know how many bytes // will be written src.position(pos); - address = ((DirectBuffer)buf).address(); + address = IOUtil.bufferAddress(buf) + pos; } try { @@ -657,7 +663,7 @@ public void run() { result.setFailure(toIOException(x)); // release resources - releaseBufferIfSubstituted(); + releaseScopeOrCacheSubstitute(); if (overlapped != 0L) ioCache.remove(overlapped); @@ -676,8 +682,8 @@ public void run() { public void completed(int bytesTransferred, boolean canInvokeDirect) { updatePosition(bytesTransferred); - // return direct buffer to cache if substituted - releaseBufferIfSubstituted(); + // release direct buffer scope or return substitute to cache + releaseScopeOrCacheSubstitute(); // release waiters and invoke completion handler result.setResult(bytesTransferred); @@ -690,8 +696,8 @@ public void completed(int bytesTransferred, boolean canInvokeDirect) { @Override public void failed(int error, IOException x) { - // return direct buffer to cache if substituted - releaseBufferIfSubstituted(); + // release direct buffer scope or return substitute to cache + releaseScopeOrCacheSubstitute(); // release waiters and invoker completion handler if (isOpen()) { diff --git a/test/jdk/java/nio/channels/AsynchronousFileChannel/Basic.java b/test/jdk/java/nio/channels/AsynchronousFileChannel/Basic.java index bb3cf92ac01..ddd4eeddbc6 100644 --- a/test/jdk/java/nio/channels/AsynchronousFileChannel/Basic.java +++ b/test/jdk/java/nio/channels/AsynchronousFileChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @bug 4607272 5041655 6822643 6830721 6842687 * @summary Unit test for AsynchronousFileChannel * @key randomness + * @run main/othervm Basic */ import java.io.File; @@ -565,12 +566,19 @@ static void testTruncate(Path file) throws IOException { static ByteBuffer genBuffer() { int size = 1024 + rand.nextInt(16000); byte[] buf = new byte[size]; - return switch (rand.nextInt(3)) { + rand.nextBytes(buf); + return switch (rand.nextInt(5)) { case 0 -> ByteBuffer.allocateDirect(buf.length) .put(buf) .flip(); case 1 -> ByteBuffer.wrap(buf); - case 2 -> Arena.ofAuto().allocate(buf.length).asByteBuffer() + case 2 -> Arena.global().allocate(buf.length).asByteBuffer() + .put(buf) + .flip(); + case 3 -> Arena.ofAuto().allocate(buf.length).asByteBuffer() + .put(buf) + .flip(); + case 4 -> Arena.ofShared().allocate(buf.length).asByteBuffer() .put(buf) .flip(); default -> throw new InternalError("Should not reach here"); @@ -606,7 +614,7 @@ public void failed(Throwable exc, Long position) { static void readAll(final AsynchronousFileChannel ch, final ByteBuffer dst, - long position) + long position) { final CountDownLatch latch = new CountDownLatch(1); diff --git a/test/jdk/java/nio/channels/etc/MemorySegments.java b/test/jdk/java/nio/channels/etc/MemorySegments.java index 2d82d855fa2..5f6b0114d50 100644 --- a/test/jdk/java/nio/channels/etc/MemorySegments.java +++ b/test/jdk/java/nio/channels/etc/MemorySegments.java @@ -26,7 +26,7 @@ * @bug 8333849 8358958 * @summary Test ByteChannel and AsycnhronousByteChannel implementations with ByteBuffers * that are views of a MemorySegment - * @run junit MemorySegments + * @run junit/othervm MemorySegments */ import java.io.IOException; @@ -54,10 +54,7 @@ import java.util.stream.Stream; import static java.nio.file.StandardOpenOption.*; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.condition.DisabledOnOs; -import org.junit.jupiter.api.condition.OS; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import static org.junit.jupiter.api.Assertions.*; @@ -653,7 +650,6 @@ void testFileChannelScatteringRead(Supplier arenaSupplier) throws IOExcep /** * AsynchronousFileChannel read/write(ByteBuffer). */ - @DisabledOnOs(OS.WINDOWS) @ParameterizedTest @MethodSource("arenaSuppliers") void testAsyncFileChannelReadWrite(Supplier arenaSupplier) throws Throwable { @@ -701,7 +697,6 @@ void testAsyncFileChannelReadWrite(Supplier arenaSupplier) throws Throwab /** * Test closing a shared arena while AsynchronousFileChannel.write in progress. */ - @Disabled @RepeatedTest(20) void testAsyncFileChannelWriteRacingArenaClose() throws Exception { Path file = Files.createTempFile(Path.of(""), "foo", ".dat"); From e55ddabffa90e28d22f546b387007fe4e434c3e0 Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Mon, 16 Jun 2025 18:20:28 +0000 Subject: [PATCH 076/213] 8359223: HttpClient: Remove leftovers from the SecurityManager cleanup Reviewed-by: dfuchs --- .../FilePublisher/FilePublisherPermsTest.java | 255 ---------- .../FilePublisher/SecureZipFSProvider.java | 446 ------------------ .../FilePublisherTest.java | 0 3 files changed, 701 deletions(-) delete mode 100644 test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java delete mode 100644 test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java rename test/jdk/java/net/httpclient/{FilePublisher => }/FilePublisherTest.java (100%) diff --git a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java deleted file mode 100644 index bafe1496a86..00000000000 --- a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * 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 - * 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 8235459 - * @summary Confirm that HttpRequest.BodyPublishers#ofFile(Path) - * works as expected - * @library /test/lib /test/jdk/java/net/httpclient/lib - * @build jdk.httpclient.test.lib.common.HttpServerAdapters jdk.test.lib.net.SimpleSSLContext - * SecureZipFSProvider - * @run testng/othervm FilePublisherPermsTest - */ - -import jdk.test.lib.net.SimpleSSLContext; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import javax.net.ssl.SSLContext; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpRequest; -import java.net.http.HttpRequest.BodyPublisher; -import java.net.http.HttpRequest.BodyPublishers; -import java.net.http.HttpResponse; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.*; -import java.util.Map; -import jdk.httpclient.test.lib.common.HttpServerAdapters; - -import static java.lang.System.out; -import static java.net.http.HttpClient.Builder.NO_PROXY; -import static java.net.http.HttpClient.Version.HTTP_1_1; -import static java.net.http.HttpClient.Version.HTTP_2; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; - -public class FilePublisherPermsTest implements HttpServerAdapters { - - SSLContext sslContext; - HttpServerAdapters.HttpTestServer httpTestServer; // HTTP/1.1 [ 4 servers ] - HttpServerAdapters.HttpTestServer httpsTestServer; // HTTPS/1.1 - HttpServerAdapters.HttpTestServer http2TestServer; // HTTP/2 ( h2c ) - HttpServerAdapters.HttpTestServer https2TestServer; // HTTP/2 ( h2 ) - String httpURI; - String httpsURI; - String http2URI; - String https2URI; - - FileSystem zipFs; - static Path zipFsPath; - static Path defaultFsPath; - - String policyFile; - - // Default file system set up - static final String DEFAULT_FS_MSG = "default fs"; - - private Path defaultFsFile() throws Exception { - var file = Path.of("defaultFile.txt"); - if (Files.notExists(file)) { - Files.createFile(file); - Files.writeString(file, DEFAULT_FS_MSG); - } - assertEquals(Files.readString(file), DEFAULT_FS_MSG); - return file; - } - - @DataProvider(name = "defaultFsData") - public Object[][] defaultFsData() { - return new Object[][]{ - { httpURI, defaultFsPath }, - { httpsURI, defaultFsPath }, - { http2URI, defaultFsPath }, - { https2URI, defaultFsPath }, - { httpURI, defaultFsPath }, - { httpsURI, defaultFsPath }, - { http2URI, defaultFsPath }, - { https2URI, defaultFsPath }, - }; - } - - @Test(dataProvider = "defaultFsData") - public void testDefaultFs(String uriString, Path path) - throws Exception { - out.printf("\n\n--- testDefaultFs(%s, %s): starting\n", - uriString, path); - BodyPublisher bodyPublisher = BodyPublishers.ofFile(path); - send(uriString, bodyPublisher); - } - - // Zip File system set up - static final String ZIP_FS_MSG = "zip fs"; - - static FileSystem newZipFs(Path zipFile) throws Exception { - return FileSystems.newFileSystem(zipFile, Map.of("create", "true")); - } - - static FileSystem newSecureZipFs(Path zipFile) throws Exception { - FileSystem fs = newZipFs(zipFile); - return new SecureZipFSProvider(fs.provider()).newFileSystem(fs); - } - - static Path zipFsFile(FileSystem fs) throws Exception { - var file = fs.getPath("fileInZip.txt"); - if (Files.notExists(file)) { - Files.createFile(file); - Files.writeString(file, ZIP_FS_MSG); - } - assertEquals(Files.readString(file), ZIP_FS_MSG); - return file; - } - - @DataProvider(name = "zipFsData") - public Object[][] zipFsData() { - return new Object[][]{ - { httpURI, zipFsPath }, - { httpsURI, zipFsPath }, - { http2URI, zipFsPath }, - { https2URI, zipFsPath }, - { httpURI, zipFsPath }, - { httpsURI, zipFsPath }, - { http2URI, zipFsPath }, - { https2URI, zipFsPath }, - }; - } - - @Test(dataProvider = "zipFsData") - public void testZipFs(String uriString, Path path) throws Exception { - out.printf("\n\n--- testZipFsCustomPerm(%s, %s): starting\n", uriString, path); - BodyPublisher bodyPublisher = BodyPublishers.ofFile(path); - send(uriString, bodyPublisher); - } - - @Test - public void testFileNotFound() throws Exception { - out.printf("\n\n--- testFileNotFound(): starting\n"); - var zipPath = Path.of("fileNotFound.zip"); - try (FileSystem fs = newZipFs(zipPath)) { - Path fileInZip = zipFsFile(fs); - Files.deleteIfExists(fileInZip); - BodyPublishers.ofFile(fileInZip); - fail(); - } catch (FileNotFoundException e) { - out.println("Caught expected: " + e); - } - var path = Path.of("fileNotFound.txt"); - try { - Files.deleteIfExists(path); - BodyPublishers.ofFile(path); - fail(); - } catch (FileNotFoundException e) { - out.println("Caught expected: " + e); - } - } - - private void send(String uriString, BodyPublisher bodyPublisher) - throws Exception { - HttpClient client = HttpClient.newBuilder() - .proxy(NO_PROXY) - .sslContext(sslContext) - .build(); - var req = HttpRequest.newBuilder(URI.create(uriString)) - .POST(bodyPublisher) - .build(); - client.send(req, HttpResponse.BodyHandlers.discarding()); - } - - - static class HttpEchoHandler implements HttpServerAdapters.HttpTestHandler { - @Override - public void handle(HttpServerAdapters.HttpTestExchange t) throws IOException { - try (InputStream is = t.getRequestBody(); - OutputStream os = t.getResponseBody()) { - byte[] bytes = is.readAllBytes(); - t.sendResponseHeaders(200, bytes.length); - os.write(bytes); - } - } - } - - @BeforeTest - public void setup() throws Exception { - sslContext = new SimpleSSLContext().get(); - if (sslContext == null) - throw new AssertionError("Unexpected null sslContext"); - - zipFs = newSecureZipFs(Path.of("file.zip")); - zipFsPath = zipFsFile(zipFs); - defaultFsPath = defaultFsFile(); - - httpTestServer = HttpServerAdapters.HttpTestServer.create(HTTP_1_1); - httpTestServer.addHandler( - new FilePublisherPermsTest.HttpEchoHandler(), "/http1/echo"); - httpURI = "http://" + httpTestServer.serverAuthority() + "/http1/echo"; - - httpsTestServer = HttpServerAdapters.HttpTestServer.create(HTTP_1_1, sslContext); - httpsTestServer.addHandler( - new FilePublisherPermsTest.HttpEchoHandler(), "/https1/echo"); - httpsURI = "https://" + httpsTestServer.serverAuthority() + "/https1/echo"; - - http2TestServer = HttpServerAdapters.HttpTestServer.create(HTTP_2); - http2TestServer.addHandler( - new FilePublisherPermsTest.HttpEchoHandler(), "/http2/echo"); - http2URI = "http://" + http2TestServer.serverAuthority() + "/http2/echo"; - - https2TestServer = HttpServerAdapters.HttpTestServer.create(HTTP_2, sslContext); - https2TestServer.addHandler( - new FilePublisherPermsTest.HttpEchoHandler(), "/https2/echo"); - https2URI = "https://" + https2TestServer.serverAuthority() + "/https2/echo"; - - httpTestServer.start(); - httpsTestServer.start(); - http2TestServer.start(); - https2TestServer.start(); - } - - @AfterTest - public void teardown() throws Exception { - httpTestServer.stop(); - httpsTestServer.stop(); - http2TestServer.stop(); - https2TestServer.stop(); - zipFs.close(); - } -} diff --git a/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java b/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java deleted file mode 100644 index 00f532ba47c..00000000000 --- a/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java +++ /dev/null @@ -1,446 +0,0 @@ -/* - * 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 - * 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.net.URI; -import java.nio.channels.FileChannel; -import java.nio.channels.SeekableByteChannel; -import java.nio.file.AccessMode; -import java.nio.file.CopyOption; -import java.nio.file.DirectoryStream; -import java.nio.file.FileStore; -import java.nio.file.FileSystem; -import java.nio.file.LinkOption; -import java.nio.file.OpenOption; -import java.nio.file.Path; -import java.nio.file.PathMatcher; -import java.nio.file.ProviderMismatchException; -import java.nio.file.WatchEvent; -import java.nio.file.WatchKey; -import java.nio.file.WatchService; -import java.nio.file.attribute.BasicFileAttributes; -import java.nio.file.attribute.FileAttribute; -import java.nio.file.attribute.FileAttributeView; -import java.nio.file.attribute.UserPrincipalLookupService; -import java.nio.file.spi.FileSystemProvider; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public class SecureZipFSProvider extends FileSystemProvider { - private final ConcurrentHashMap map = - new ConcurrentHashMap<>(); - private final FileSystemProvider defaultProvider; - - public SecureZipFSProvider(FileSystemProvider provider) { - defaultProvider = provider; - } - - @Override - public String getScheme() { - return "jar"; - } - - public FileSystem newFileSystem(FileSystem fs) { - return map.computeIfAbsent(fs, (sfs) -> - new SecureZipFS(this, fs)); - } - - @Override - public FileSystem newFileSystem(URI uri, Map env) - throws IOException { - FileSystem fs = defaultProvider.newFileSystem(uri, env); - return map.computeIfAbsent(fs, (sfs) -> - new SecureZipFS(this, fs) - ); - } - - @Override - public FileSystem getFileSystem(URI uri) { - return map.get(defaultProvider.getFileSystem(uri)); - } - - @Override - public Path getPath(URI uri) { - Path p = defaultProvider.getPath(uri); - return map.get(defaultProvider.getFileSystem(uri)).wrap(p); - } - - @Override - public InputStream newInputStream(Path path, OpenOption... options) - throws IOException { - Path p = toTestPath(path).unwrap(); - return defaultProvider.newInputStream(p, options); - } - - @Override - public SeekableByteChannel newByteChannel(Path path, - Set options, - FileAttribute... attrs) - throws IOException { - Path p = toTestPath(path).unwrap(); - return defaultProvider.newByteChannel(p, options, attrs); - } - - @Override - public FileChannel newFileChannel(Path path, - Set options, - FileAttribute... attrs) - throws IOException { - Path p = toTestPath(path).unwrap(); - return defaultProvider.newFileChannel(p, options, attrs); - } - - - @Override - public DirectoryStream newDirectoryStream(Path dir, - DirectoryStream.Filter filter) { - throw new RuntimeException("not implemented"); - } - - @Override - public void createDirectory(Path dir, FileAttribute... attrs) - throws IOException { - Path p = toTestPath(dir).unwrap(); - defaultProvider.createDirectory(p, attrs); - } - - @Override - public void delete(Path path) throws IOException { - Path p = toTestPath(path).unwrap(); - defaultProvider.delete(p); - } - - @Override - public void copy(Path source, Path target, CopyOption... options) - throws IOException { - Path sp = toTestPath(source).unwrap(); - Path tp = toTestPath(target).unwrap(); - defaultProvider.copy(sp, tp, options); - } - - @Override - public void move(Path source, Path target, CopyOption... options) - throws IOException { - Path sp = toTestPath(source).unwrap(); - Path tp = toTestPath(target).unwrap(); - defaultProvider.move(sp, tp, options); - } - - @Override - public boolean isSameFile(Path path, Path path2) - throws IOException { - Path p = toTestPath(path).unwrap(); - Path p2 = toTestPath(path2).unwrap(); - return defaultProvider.isSameFile(p, p2); - } - - @Override - public boolean isHidden(Path path) throws IOException { - Path p = toTestPath(path).unwrap(); - return defaultProvider.isHidden(p); - } - - @Override - public FileStore getFileStore(Path path) throws IOException { - Path p = toTestPath(path).unwrap(); - return defaultProvider.getFileStore(p); - } - - @Override - public void checkAccess(Path path, AccessMode... modes) throws IOException { - Path p = toTestPath(path).unwrap(); - defaultProvider.checkAccess(p, modes); - } - - @Override - public V getFileAttributeView(Path path, - Class type, - LinkOption... options) { - Path p = toTestPath(path).unwrap(); - return defaultProvider.getFileAttributeView(p, type, options); - } - - @Override - public A readAttributes(Path path, - Class type, - LinkOption... options) - throws IOException { - Path p = toTestPath(path).unwrap(); - return defaultProvider.readAttributes(p, type, options); - } - - @Override - public Map readAttributes(Path path, - String attributes, - LinkOption... options) - throws IOException { - Path p = toTestPath(path).unwrap(); - return defaultProvider.readAttributes(p, attributes, options); - } - - @Override - public void setAttribute(Path path, String attribute, - Object value, LinkOption... options) - throws IOException { - Path p = toTestPath(path).unwrap(); - defaultProvider.setAttribute(p, attribute, options); - } - - // Checks that the given file is a TestPath - static TestPath toTestPath(Path obj) { - if (obj == null) - throw new NullPointerException(); - if (!(obj instanceof TestPath)) - throw new ProviderMismatchException(); - return (TestPath) obj; - } - - static class SecureZipFS extends FileSystem { - private final SecureZipFSProvider provider; - private final FileSystem delegate; - - public SecureZipFS(SecureZipFSProvider provider, FileSystem delegate) { - this.provider = provider; - this.delegate = delegate; - } - - Path wrap(Path path) { - return (path != null) ? new TestPath(this, path) : null; - } - - Path unwrap(Path wrapper) { - if (wrapper == null) - throw new NullPointerException(); - if (!(wrapper instanceof TestPath)) - throw new ProviderMismatchException(); - return ((TestPath) wrapper).unwrap(); - } - - @Override - public FileSystemProvider provider() { - return provider; - } - - @Override - public void close() throws IOException { - delegate.close(); - } - - @Override - public boolean isOpen() { - return delegate.isOpen(); - } - - @Override - public boolean isReadOnly() { - return delegate.isReadOnly(); - } - - @Override - public String getSeparator() { - return delegate.getSeparator(); - } - - @Override - public Iterable getRootDirectories() { - return delegate.getRootDirectories(); - } - - @Override - public Iterable getFileStores() { - return delegate.getFileStores(); - } - - @Override - public Set supportedFileAttributeViews() { - return delegate.supportedFileAttributeViews(); - } - - @Override - public Path getPath(String first, String... more) { - return wrap(delegate.getPath(first, more)); - } - - @Override - public PathMatcher getPathMatcher(String syntaxAndPattern) { - return delegate.getPathMatcher(syntaxAndPattern); - } - - @Override - public UserPrincipalLookupService getUserPrincipalLookupService() { - return delegate.getUserPrincipalLookupService(); - } - - @Override - public WatchService newWatchService() throws IOException { - return delegate.newWatchService(); - } - } - - static class TestPath implements Path { - private final SecureZipFS fs; - private final Path delegate; - - TestPath(SecureZipFS fs, Path delegate) { - this.fs = fs; - this.delegate = delegate; - } - - Path unwrap() { - return delegate; - } - - @Override - public SecureZipFS getFileSystem() { - return fs; - } - - @Override - public boolean isAbsolute() { - return delegate.isAbsolute(); - } - - @Override - public Path getRoot() { - return fs.wrap(delegate.getRoot()); - } - - @Override - public Path getFileName() { - return fs.wrap(delegate.getFileName()); - } - - @Override - public Path getParent() { - return fs.wrap(delegate.getParent()); - } - - @Override - public int getNameCount() { - return delegate.getNameCount(); - } - - @Override - public Path getName(int index) { - return fs.wrap(delegate.getName(index)); - } - - @Override - public Path subpath(int beginIndex, int endIndex) { - return fs.wrap(delegate.subpath(beginIndex, endIndex)); - } - - @Override - public boolean startsWith(Path other) { - return delegate.startsWith(other); - } - - @Override - public boolean endsWith(Path other) { - return delegate.endsWith(other); - } - - @Override - public Path normalize() { - return fs.wrap(delegate.normalize()); - } - - @Override - public Path resolve(Path other) { - return fs.wrap(delegate.resolve(fs.wrap(other))); - } - - @Override - public Path relativize(Path other) { - return fs.wrap(delegate.relativize(fs.wrap(other))); - } - - @Override - public URI toUri() { - String ssp = delegate.toUri().getSchemeSpecificPart(); - return URI.create(fs.provider().getScheme() + ":" + ssp); - } - - @Override - public Path toAbsolutePath() { - return fs.wrap(delegate.toAbsolutePath()); - } - - @Override - public Path toRealPath(LinkOption... options) throws IOException { - return fs.wrap(delegate.toRealPath(options)); - } - - @Override - public WatchKey register(WatchService watcher, - WatchEvent.Kind[] events, - WatchEvent.Modifier... modifiers) - throws IOException { - return delegate.register(watcher, events, modifiers); - } - - @Override - public Iterator iterator() { - final Iterator itr = delegate.iterator(); - return new Iterator<>() { - @Override - public boolean hasNext() { - return itr.hasNext(); - } - - @Override - public Path next() { - return fs.wrap(itr.next()); - } - - @Override - public void remove() { - itr.remove(); - } - }; - } - - @Override - public int compareTo(Path other) { - return delegate.compareTo(fs.unwrap(other)); - } - - @Override - public int hashCode() { - return delegate.hashCode(); - } - - @Override - public boolean equals(Object other) { - return other instanceof TestPath && delegate.equals(fs.unwrap((TestPath) other)); - } - - @Override - public String toString() { - return delegate.toString(); - } - } -} diff --git a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.java b/test/jdk/java/net/httpclient/FilePublisherTest.java similarity index 100% rename from test/jdk/java/net/httpclient/FilePublisher/FilePublisherTest.java rename to test/jdk/java/net/httpclient/FilePublisherTest.java From a16d23557b101504ed2ff95cf1a3c5ba11afe33d Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Tue, 17 Jun 2025 05:38:59 +0000 Subject: [PATCH 077/213] 8359402: Test CloseDescriptors.java should throw SkippedException when there is no lsof/sctp Reviewed-by: vyazici, jpai --- .../sun/nio/sctp/SctpChannel/CloseDescriptors.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java b/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java index c8ed8a881f6..0b3ce6ae039 100644 --- a/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java +++ b/test/jdk/com/sun/nio/sctp/SctpChannel/CloseDescriptors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,8 @@ * @bug 8238274 * @summary Potential leak file descriptor for SCTP * @requires (os.family == "linux") + * @library /test/lib + * @build jtreg.SkippedException * @run main/othervm/timeout=250 CloseDescriptors */ @@ -52,9 +54,7 @@ public class CloseDescriptors { public static void main(String[] args) throws Exception { if (!Util.isSCTPSupported()) { - System.out.println("SCTP protocol is not supported"); - System.out.println("Test cannot be run"); - return; + throw new jtreg.SkippedException("SCTP protocol is not supported"); } List lsofDirs = List.of("/usr/bin", "/usr/sbin"); @@ -63,9 +63,7 @@ public static void main(String[] args) throws Exception { .filter(f -> Files.isExecutable(f)) .findFirst(); if (!lsof.isPresent()) { - System.out.println("Cannot locate lsof in " + lsofDirs); - System.out.println("Test cannot be run"); - return; + throw new jtreg.SkippedException("Cannot locate lsof in " + lsofDirs); } try (ServerSocket ss = new ServerSocket(0)) { From ff75f763c0a91534ab593a43e2ace741d05b0ccb Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Tue, 17 Jun 2025 07:16:19 +0000 Subject: [PATCH 078/213] 8351645: C2: Assertion failures in Expand/CompressBits idealizations with TOP Co-authored-by: Emanuel Peter Reviewed-by: epeter, sviswanathan --- src/hotspot/share/opto/intrinsicnode.cpp | 8 +- .../c2/gvn/TestCompressExpandTopInput.java | 129 ++++++++++++++++++ 2 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/gvn/TestCompressExpandTopInput.java diff --git a/src/hotspot/share/opto/intrinsicnode.cpp b/src/hotspot/share/opto/intrinsicnode.cpp index e67352d85bd..06317a9482c 100644 --- a/src/hotspot/share/opto/intrinsicnode.cpp +++ b/src/hotspot/share/opto/intrinsicnode.cpp @@ -135,7 +135,7 @@ Node* CompressBitsNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* src = in(1); Node* mask = in(2); if (bottom_type()->isa_int()) { - if (mask->Opcode() == Op_LShiftI && phase->type(mask->in(1))->is_int()->is_con()) { + if (mask->Opcode() == Op_LShiftI && phase->type(mask->in(1))->isa_int() && phase->type(mask->in(1))->is_int()->is_con()) { // compress(x, 1 << n) == (x >> n & 1) if (phase->type(mask->in(1))->higher_equal(TypeInt::ONE)) { Node* rshift = phase->transform(new RShiftINode(in(1), mask->in(2))); @@ -153,7 +153,7 @@ Node* CompressBitsNode::Ideal(PhaseGVN* phase, bool can_reshape) { } } else { assert(bottom_type()->isa_long(), ""); - if (mask->Opcode() == Op_LShiftL && phase->type(mask->in(1))->is_long()->is_con()) { + if (mask->Opcode() == Op_LShiftL && phase->type(mask->in(1))->isa_long() && phase->type(mask->in(1))->is_long()->is_con()) { // compress(x, 1 << n) == (x >> n & 1) if (phase->type(mask->in(1))->higher_equal(TypeLong::ONE)) { Node* rshift = phase->transform(new RShiftLNode(in(1), mask->in(2))); @@ -193,7 +193,7 @@ Node* ExpandBitsNode::Ideal(PhaseGVN* phase, bool can_reshape) { Node* src = in(1); Node* mask = in(2); if (bottom_type()->isa_int()) { - if (mask->Opcode() == Op_LShiftI && phase->type(mask->in(1))->is_int()->is_con()) { + if (mask->Opcode() == Op_LShiftI && phase->type(mask->in(1))->isa_int() && phase->type(mask->in(1))->is_int()->is_con()) { // expand(x, 1 << n) == (x & 1) << n if (phase->type(mask->in(1))->higher_equal(TypeInt::ONE)) { Node* andnode = phase->transform(new AndINode(in(1), phase->makecon(TypeInt::ONE))); @@ -210,7 +210,7 @@ Node* ExpandBitsNode::Ideal(PhaseGVN* phase, bool can_reshape) { } } else { assert(bottom_type()->isa_long(), ""); - if (mask->Opcode() == Op_LShiftL && phase->type(mask->in(1))->is_long()->is_con()) { + if (mask->Opcode() == Op_LShiftL && phase->type(mask->in(1))->isa_long() && phase->type(mask->in(1))->is_long()->is_con()) { // expand(x, 1 << n) == (x & 1) << n if (phase->type(mask->in(1))->higher_equal(TypeLong::ONE)) { Node* andnode = phase->transform(new AndLNode(in(1), phase->makecon(TypeLong::ONE))); diff --git a/test/hotspot/jtreg/compiler/c2/gvn/TestCompressExpandTopInput.java b/test/hotspot/jtreg/compiler/c2/gvn/TestCompressExpandTopInput.java new file mode 100644 index 00000000000..fa78a11f6a1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/gvn/TestCompressExpandTopInput.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8351645 + * @summary C2: ExpandBitsNode::Ideal hits assert because of TOP input + * @library /test/lib / + * @run driver compiler.intrinsics.TestCompressExpandTopInput + */ + +package compiler.intrinsics; + +import compiler.lib.ir_framework.*; +import compiler.lib.verify.*; +import java.util.stream.IntStream; +import java.util.stream.LongStream; + +public class TestCompressExpandTopInput { + + public static int [] array_I0 = IntStream.range(0, 10000).toArray(); + public static int [] array_I1 = IntStream.range(10000, 20000).toArray(); + public static long [] array_L0 = LongStream.range(0, 10000).toArray(); + public static long [] array_L1 = LongStream.range(10000, 20000).toArray(); + + public static int oneI = 1; + public static long oneL = 1L; + + public static long [] GOLD_COMPRESS_LONG = testCompressBitsLong(); + public static long [] GOLD_EXPAND_LONG = testExpandBitsLong(); + public static int [] GOLD_COMPRESS_INT = testCompressBitsInt(); + public static int [] GOLD_EXPAND_INT = testExpandBitsInt(); + + @Test + public static long[] testExpandBitsLong() { + long[] out = new long[10000]; + for (int i = 0; i < out.length; i++) { + long y = array_L0[i] % oneL; + long x = (array_L1[i] | 4294967298L) << -7640610671680100954L; + out[i] = Long.expand(y, x); + } + return out; + } + + @Check(test="testExpandBitsLong") + public static void checkExpandBitsLong(long [] actual) { + for (int i = 0; i < GOLD_EXPAND_LONG.length; i++) { + Verify.checkEQ(GOLD_EXPAND_LONG[i], actual[i]); + } + } + + @Test + public static long[] testCompressBitsLong() { + long[] out = new long[10000]; + for (int i = 0; i < out.length; i++) { + long y = array_L0[i] % oneL; + long x = (array_L1[i] | 4294967298L) << -7640610671680100954L; + out[i] = Long.compress(y, x); + } + return out; + } + + @Check(test="testCompressBitsLong") + public static void checkCompressBitsLong(long [] actual) { + for (int i = 0; i < GOLD_COMPRESS_LONG.length; i++) { + Verify.checkEQ(GOLD_COMPRESS_LONG[i], actual[i]); + } + } + + @Test + public static int[] testExpandBitsInt() { + int[] out = new int[10000]; + for (int i = 0; i < out.length; i++) { + int y = array_I0[i] % oneI; + int x = (array_I1[i] | 22949672) << -76406101; + out[i] = Integer.expand(y, x); + } + return out; + } + + @Check(test="testExpandBitsInt") + public static void checkExpandBitsInt(int [] actual) { + for (int i = 0; i < GOLD_EXPAND_INT.length; i++) { + Verify.checkEQ(GOLD_EXPAND_INT[i], actual[i]); + } + } + + @Test + public static int[] testCompressBitsInt() { + int[] out = new int[10000]; + for (int i = 0; i < out.length; i++) { + int y = array_I0[i] % oneI; + int x = (array_I1[i] | 429497) << -764061068; + out[i] = Integer.compress(y, x); + } + return out; + } + + @Check(test="testCompressBitsInt") + public static void checkCompressBitsInt(int [] actual) { + for (int i = 0; i < GOLD_COMPRESS_INT.length; i++) { + Verify.checkEQ(GOLD_COMPRESS_INT[i], actual[i]); + } + } + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:+StressIGVN"); + } +} From f7cd3fad2400cd3a07d8a3a44d86d5dc4d23913e Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Tue, 17 Jun 2025 08:32:17 +0000 Subject: [PATCH 079/213] 8332623: Remove setTTL()/getTTL() methods from DatagramSocketImpl/MulticastSocket and MulticastSocket.send(DatagramPacket, byte) Reviewed-by: dfuchs, alanb --- .../classes/java/net/DatagramSocketImpl.java | 26 +----- .../classes/java/net/MulticastSocket.java | 81 +------------------ .../classes/java/net/NetMulticastSocket.java | 70 +--------------- .../sun/nio/ch/DatagramSocketAdaptor.java | 47 +---------- .../net/DatagramSocket/AddressNotSet.java | 40 +-------- .../DatagramSocketMulticasting.java | 4 +- .../OldDatagramSocketImplTest.java | 10 +-- .../java/net/DatagramSocket/SendCheck.java | 16 +--- .../java/net/MyDatagramSocketImplFactory.java | 11 +-- .../net/DatagramSocketImpl/TestCreate.java | 4 +- .../TestDefaultBehavior.java | 4 +- .../net/MulticastSocket/MulticastTTL.java | 61 -------------- .../net/MulticastSocket/SendPortZero.java | 3 +- .../MulticastSocket/SetLoopbackOption.java | 12 +-- .../net/MulticastSocket/SetTTLAndGetTTL.java | 48 ----------- .../java/net/MulticastSocket/SetTTLTo0.java | 3 +- .../net/SocketOption/CachedImplOptions.java | 4 +- .../net/SocketOption/ImmutableOptions.java | 6 +- .../DatagramChannel/AdaptorMulticasting.java | 20 +---- 19 files changed, 25 insertions(+), 445 deletions(-) delete mode 100644 test/jdk/java/net/MulticastSocket/MulticastTTL.java delete mode 100644 test/jdk/java/net/MulticastSocket/SetTTLAndGetTTL.java diff --git a/src/java.base/share/classes/java/net/DatagramSocketImpl.java b/src/java.base/share/classes/java/net/DatagramSocketImpl.java index 54093a9d5f1..71db2c0a427 100644 --- a/src/java.base/share/classes/java/net/DatagramSocketImpl.java +++ b/src/java.base/share/classes/java/net/DatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -162,30 +162,6 @@ protected void disconnect() { */ protected abstract void receive(DatagramPacket p) throws IOException; - /** - * Set the TTL (time-to-live) option. - * @param ttl a byte specifying the TTL value - * - * @deprecated use setTimeToLive instead. - * @throws IOException if an I/O exception occurs while setting - * the time-to-live option. - * @see #getTTL() - */ - @Deprecated(forRemoval = true, since = "1.2") - protected abstract void setTTL(byte ttl) throws IOException; - - /** - * Retrieve the TTL (time-to-live) option. - * - * @throws IOException if an I/O exception occurs - * while retrieving the time-to-live option - * @deprecated use getTimeToLive instead. - * @return a byte representing the TTL value - * @see #setTTL(byte) - */ - @Deprecated(forRemoval = true, since = "1.2") - protected abstract byte getTTL() throws IOException; - /** * Set the TTL (time-to-live) option. * @param ttl an {@code int} specifying the time-to-live value diff --git a/src/java.base/share/classes/java/net/MulticastSocket.java b/src/java.base/share/classes/java/net/MulticastSocket.java index 367aaf3a9ea..ac1b40c2767 100644 --- a/src/java.base/share/classes/java/net/MulticastSocket.java +++ b/src/java.base/share/classes/java/net/MulticastSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,26 +188,6 @@ public MulticastSocket(SocketAddress bindaddr) throws IOException { this(createDelegate(bindaddr, MulticastSocket.class)); } - /** - * Set the default time-to-live for multicast packets sent out - * on this {@code MulticastSocket} in order to control the - * scope of the multicasts. - * - *

    The ttl is an unsigned 8-bit quantity, and so must be - * in the range {@code 0 <= ttl <= 0xFF }. - * - * @param ttl the time-to-live - * @throws IOException if an I/O exception occurs - * while setting the default time-to-live value, or the socket is closed. - * @deprecated use the {@link #setTimeToLive(int)} method instead, which uses - * int instead of byte as the type for ttl. - * @see #getTTL() - */ - @Deprecated(forRemoval = true, since = "1.2") - public void setTTL(byte ttl) throws IOException { - delegate().setTTL(ttl); - } - /** * Set the default time-to-live for multicast packets sent out * on this {@code MulticastSocket} in order to control the @@ -237,22 +217,6 @@ public void setTimeToLive(int ttl) throws IOException { delegate().setTimeToLive(ttl); } - /** - * Get the default time-to-live for multicast packets sent out on - * the socket. - * - * @throws IOException if an I/O exception occurs - * while getting the default time-to-live value, or the socket is closed. - * @return the default time-to-live value - * @deprecated use the {@link #getTimeToLive()} method instead, - * which returns an int instead of a byte. - * @see #setTTL(byte) - */ - @Deprecated(forRemoval = true, since = "1.2") - public byte getTTL() throws IOException { - return delegate().getTTL(); - } - /** * Get the default time-to-live for multicast packets sent out on * the socket. @@ -466,47 +430,4 @@ public void setLoopbackMode(boolean disable) throws SocketException { public boolean getLoopbackMode() throws SocketException { return delegate().getLoopbackMode(); } - - /** - * Sends a datagram packet to the destination, with a TTL (time-to-live) - * other than the default for the socket. This method - * need only be used in instances where a particular TTL is desired; - * otherwise it is preferable to set a TTL once on the socket, and - * use that default TTL for all packets. This method does not - * alter the default TTL for the socket. Its behavior may be - * affected by {@code setInterface}. - * - * @param p is the packet to be sent. The packet should contain - * the destination multicast ip address and the data to be sent. - * One does not need to be the member of the group to send - * packets to a destination multicast address. - * @param ttl optional time to live for multicast packet. - * default ttl is 1. - * - * @throws IOException if an I/O error occurs, or the socket is closed. - * @throws PortUnreachableException may be thrown if the socket is connected - * to a currently unreachable destination. Note, there is no - * guarantee that the exception will be thrown. - * @throws IllegalArgumentException if the socket is connected, - * and connected address and packet address differ, or - * if the socket is not connected and the packet address - * is not set or if its port is out of range. - * - * - * @deprecated Use the following code or its equivalent instead: - *

    {@code   ......
    -     *  int ttl = mcastSocket.getOption(StandardSocketOptions.IP_MULTICAST_TTL);
    -     *  mcastSocket.setOption(StandardSocketOptions.IP_MULTICAST_TTL, newttl);
    -     *  mcastSocket.send(p);
    -     *  mcastSocket.setOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl);
    -     *  ......}
    - * - * @see DatagramSocket#send - * @see DatagramSocket#receive - */ - @Deprecated(forRemoval = true, since = "1.4") - public void send(DatagramPacket p, byte ttl) - throws IOException { - delegate().send(p, ttl); - } } diff --git a/src/java.base/share/classes/java/net/NetMulticastSocket.java b/src/java.base/share/classes/java/net/NetMulticastSocket.java index bce2e945335..80cb997102f 100644 --- a/src/java.base/share/classes/java/net/NetMulticastSocket.java +++ b/src/java.base/share/classes/java/net/NetMulticastSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -567,12 +567,6 @@ public Set> supportedOptions() { */ private boolean interfaceSet; - /** - * The lock on the socket's TTL. This is for set/getTTL and - * send(packet,ttl). - */ - private final Object ttlLock = new Object(); - /** * The lock on the socket's interface - used by setInterface * and getInterface @@ -584,14 +578,6 @@ public Set> supportedOptions() { */ private InetAddress infAddress = null; - @Override - @SuppressWarnings("removal") - public void setTTL(byte ttl) throws IOException { - if (isClosed()) - throw new SocketException("Socket is closed"); - getImpl().setTTL(ttl); - } - @Override public void setTimeToLive(int ttl) throws IOException { if (ttl < 0 || ttl > 255) { @@ -602,14 +588,6 @@ public void setTimeToLive(int ttl) throws IOException { getImpl().setTimeToLive(ttl); } - @Override - @SuppressWarnings("removal") - public byte getTTL() throws IOException { - if (isClosed()) - throw new SocketException("Socket is closed"); - return getImpl().getTTL(); - } - @Override public int getTimeToLive() throws IOException { if (isClosed()) @@ -796,50 +774,4 @@ public void setLoopbackMode(boolean disable) throws SocketException { public boolean getLoopbackMode() throws SocketException { return ((Boolean)getImpl().getOption(SocketOptions.IP_MULTICAST_LOOP)).booleanValue(); } - - @SuppressWarnings("removal") - @Override - public void send(DatagramPacket p, byte ttl) - throws IOException { - if (isClosed()) - throw new SocketException("Socket is closed"); - synchronized(ttlLock) { - synchronized(p) { - InetAddress packetAddress = p.getAddress(); - checkAddress(packetAddress, "send"); - if (connectState == ST_NOT_CONNECTED) { - if (packetAddress == null) { - throw new IllegalArgumentException("Address not set"); - } - } else { - // we're connected - if (packetAddress == null) { - p.setAddress(connectedAddress); - p.setPort(connectedPort); - } else if ((!packetAddress.equals(connectedAddress)) || - p.getPort() != connectedPort) { - throw new IllegalArgumentException("connected address and packet address" + - " differ"); - } - } - byte dttl = getTTL(); - try { - if (ttl != dttl) { - // set the ttl - getImpl().setTTL(ttl); - } - if (p.getPort() == 0) { - throw new SocketException("Can't send to port 0"); - } - // call the datagram method to send - getImpl().send(p); - } finally { - // set it back to default - if (ttl != dttl) { - getImpl().setTTL(dttl); - } - } - } // synch p - } //synch ttl - } //method } diff --git a/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java b/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java index 44b05f97472..a9962d19400 100644 --- a/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java +++ b/src/java.base/share/classes/sun/nio/ch/DatagramSocketAdaptor.java @@ -50,7 +50,6 @@ import java.nio.channels.MembershipKey; import java.util.Objects; import java.util.Set; -import java.util.concurrent.locks.ReentrantLock; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static jdk.internal.util.Exceptions.formatMsg; @@ -372,44 +371,19 @@ public Set> supportedOptions() { // -- java.net.MulticastSocket -- - // used to coordinate changing TTL with the deprecated send method - private final ReentrantLock sendLock = new ReentrantLock(); - // cached outgoing interface (for use by setInterface/getInterface) private final Object outgoingInterfaceLock = new Object(); private NetworkInterface outgoingNetworkInterface; private InetAddress outgoingInetAddress; - @Override - @SuppressWarnings("removal") - public void setTTL(byte ttl) throws IOException { - setTimeToLive(Byte.toUnsignedInt(ttl)); - } - @Override public void setTimeToLive(int ttl) throws IOException { - sendLock.lock(); - try { - setIntOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl); - } finally { - sendLock.unlock(); - } - } - - @Override - @SuppressWarnings("removal") - public byte getTTL() throws IOException { - return (byte) getTimeToLive(); + setIntOption(StandardSocketOptions.IP_MULTICAST_TTL, ttl); } @Override public int getTimeToLive() throws IOException { - sendLock.lock(); - try { - return getIntOption(StandardSocketOptions.IP_MULTICAST_TTL); - } finally { - sendLock.unlock(); - } + return getIntOption(StandardSocketOptions.IP_MULTICAST_TTL); } @Override @@ -558,23 +532,6 @@ public boolean getLoopbackMode() throws SocketException { return !enabled; } - @Override - @SuppressWarnings("removal") - public void send(DatagramPacket p, byte ttl) throws IOException { - sendLock.lock(); - try { - int oldValue = getTimeToLive(); - try { - setTTL(ttl); - send(p); - } finally { - setTimeToLive(oldValue); - } - } finally { - sendLock.unlock(); - } - } - /** * Returns the outgoing NetworkInterface or null if not set. */ diff --git a/test/jdk/java/net/DatagramSocket/AddressNotSet.java b/test/jdk/java/net/DatagramSocket/AddressNotSet.java index 0e7b28aa044..afab2c686d1 100644 --- a/test/jdk/java/net/DatagramSocket/AddressNotSet.java +++ b/test/jdk/java/net/DatagramSocket/AddressNotSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,43 +108,5 @@ private void test(DatagramSocket sock) throws Exception { p = new DatagramPacket(buf, buf.length, addr, port); sock.send(p); serversock.receive(p); - - if (sock instanceof MulticastSocket) { - sock.disconnect(); - testTTL((MulticastSocket)sock); - } - } - - private void testTTL(MulticastSocket sock) throws Exception { - out.println("Testing deprecated send TTL with " + sock.getClass()); - final byte ttl = 100; - InetAddress addr = loopbackAddress; - byte[] buf; - DatagramPacket p; - int port = serversock.getLocalPort(); - - out.println("Checking send to non-connected address ..."); - try { - out.println("Checking send with no packet address"); - buf = ("Hello, server"+(++i)).getBytes(); - p = new DatagramPacket(buf, buf.length); - sock.send(p,ttl); - throw new AssertionError("Expected IllegalArgumentException not received"); - } catch (IllegalArgumentException x) { - out.println("Got expected exception: " + x); - } - - out.println("Connecting to connected address: " + sock); - sock.connect(addr, port); - - try { - out.println("Checking send with different address than connected"); - buf = ("Hello, server"+(++i)).getBytes(); - p = new DatagramPacket(buf, buf.length, addr, port+1); - sock.send(p, ttl); - throw new AssertionError("Expected IllegalArgumentException not received"); - } catch (IllegalArgumentException x) { - out.println("Got expected exception: " + x); - } } } diff --git a/test/jdk/java/net/DatagramSocket/DatagramSocketMulticasting.java b/test/jdk/java/net/DatagramSocket/DatagramSocketMulticasting.java index 1758ff2190c..39cdf7210f7 100644 --- a/test/jdk/java/net/DatagramSocket/DatagramSocketMulticasting.java +++ b/test/jdk/java/net/DatagramSocket/DatagramSocketMulticasting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -252,7 +252,7 @@ static void testNetworkInterface(DatagramSocket s, } /** - * Test getTimeToLive/setTimeToLive/getTTL/getTTL and IP_MULTICAST_TTL socket + * Test getTimeToLive/setTimeToLive and IP_MULTICAST_TTL socket * option. */ static void testTimeToLive(DatagramSocket s) throws IOException { diff --git a/test/jdk/java/net/DatagramSocket/OldDatagramSocketImplTest.java b/test/jdk/java/net/DatagramSocket/OldDatagramSocketImplTest.java index c1a110c6619..7f8eea874ec 100644 --- a/test/jdk/java/net/DatagramSocket/OldDatagramSocketImplTest.java +++ b/test/jdk/java/net/DatagramSocket/OldDatagramSocketImplTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,14 +121,6 @@ protected int peekData(DatagramPacket p) throws IOException { @Override protected void receive(DatagramPacket p) throws IOException { } - @Override - protected void setTTL(byte ttl) throws IOException { } - - @Override - protected byte getTTL() throws IOException { - return 0; - } - @Override protected void setTimeToLive(int ttl) throws IOException { } diff --git a/test/jdk/java/net/DatagramSocket/SendCheck.java b/test/jdk/java/net/DatagramSocket/SendCheck.java index 8943e8517fa..482eadb3cf9 100644 --- a/test/jdk/java/net/DatagramSocket/SendCheck.java +++ b/test/jdk/java/net/DatagramSocket/SendCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ * @bug 8236105 * @summary Check that DatagramSocket, MulticastSocket, * DatagramSocketAdaptor and DatagramChannel all - * throw expected Execption when passed a DatagramPacket + * throw expected Exception when passed a DatagramPacket * with invalid details * @run testng SendCheck */ @@ -126,11 +126,9 @@ Object[][] providerIO() throws IOException { List senders = List.of( Sender.of(new DatagramSocket(null)), - Sender.of(new MulticastSocket(null), (byte) 0), + Sender.of(new MulticastSocket(null)), Sender.of(DatagramChannel.open()), - Sender.of(DatagramChannel.open().socket()), - Sender.of((MulticastSocket) - DatagramChannel.open().socket(), (byte) 0) + Sender.of(DatagramChannel.open().socket()) ); List testcases = new ArrayList<>(); @@ -179,12 +177,6 @@ static Sender of(DatagramSocket socket) { return new SenderImpl<>(socket, socket::send, socket::close, SE); } - static Sender of(MulticastSocket socket, byte ttl) { - SenderImpl.Send send = - (pkt) -> socket.send(pkt, ttl); - return new SenderImpl<>(socket, send, socket::close, SE); - } - static Sender of(DatagramChannel socket) { SenderImpl.Send send = (pkt) -> socket.send(ByteBuffer.wrap(pkt.getData()), diff --git a/test/jdk/java/net/DatagramSocket/SetDatagramSocketImplFactory/java.base/java/net/MyDatagramSocketImplFactory.java b/test/jdk/java/net/DatagramSocket/SetDatagramSocketImplFactory/java.base/java/net/MyDatagramSocketImplFactory.java index 41a209ccf01..41f1a33a817 100644 --- a/test/jdk/java/net/DatagramSocket/SetDatagramSocketImplFactory/java.base/java/net/MyDatagramSocketImplFactory.java +++ b/test/jdk/java/net/DatagramSocket/SetDatagramSocketImplFactory/java.base/java/net/MyDatagramSocketImplFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,15 +63,6 @@ protected void receive(DatagramPacket p) throws IOException { ds.receive(p); } - @Override - protected void setTTL(byte ttl) throws IOException { - } - - @Override - protected byte getTTL() throws IOException { - return 0; - } - @Override protected void setTimeToLive(int ttl) throws IOException { diff --git a/test/jdk/java/net/DatagramSocketImpl/TestCreate.java b/test/jdk/java/net/DatagramSocketImpl/TestCreate.java index 5a0fdf63283..81772074ae2 100644 --- a/test/jdk/java/net/DatagramSocketImpl/TestCreate.java +++ b/test/jdk/java/net/DatagramSocketImpl/TestCreate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,8 +105,6 @@ public T getOption(SocketOption name) throws IOException { @Override protected int peek(InetAddress i) { return 0; } @Override protected int peekData(DatagramPacket p) { return 0; } @Override protected void receive(DatagramPacket p) { } - @Override protected void setTTL(byte ttl) { } - @Override protected byte getTTL() { return 0; } @Override protected void setTimeToLive(int ttl) { } @Override protected int getTimeToLive() { return 0; } @Override protected void join(InetAddress inetaddr) { } diff --git a/test/jdk/java/net/DatagramSocketImpl/TestDefaultBehavior.java b/test/jdk/java/net/DatagramSocketImpl/TestDefaultBehavior.java index 760f7586c27..2e223f1820c 100644 --- a/test/jdk/java/net/DatagramSocketImpl/TestDefaultBehavior.java +++ b/test/jdk/java/net/DatagramSocketImpl/TestDefaultBehavior.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,8 +99,6 @@ public T getOption(SocketOption name) throws IOException { @Override protected int peek(InetAddress i) { return 0; } @Override protected int peekData(DatagramPacket p) { return 0; } @Override protected void receive(DatagramPacket p) { } - @Override protected void setTTL(byte ttl) { } - @Override protected byte getTTL() { return 0; } @Override protected void setTimeToLive(int ttl) { } @Override protected int getTimeToLive() { return 0; } @Override protected void join(InetAddress inetaddr) { } diff --git a/test/jdk/java/net/MulticastSocket/MulticastTTL.java b/test/jdk/java/net/MulticastSocket/MulticastTTL.java deleted file mode 100644 index 0fcc5a373d4..00000000000 --- a/test/jdk/java/net/MulticastSocket/MulticastTTL.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. - * 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 4089415 - * @summary Test MulticastSocket send for modification of ttl - * - */ -import java.io.*; -import java.net.*; - -public class MulticastTTL { - - public static void main(String args[]) throws Exception { - MulticastSocket soc = null; - DatagramPacket pac = null; - InetAddress sin = null; - byte [] array = new byte[65537]; - int port = 0; - byte old_ttl = 0; - byte new_ttl = 64; - byte ttl = 0; - - sin = InetAddress.getByName("224.80.80.80"); - soc = new MulticastSocket(); - port = soc.getLocalPort(); - old_ttl = soc.getTTL(); - pac = new DatagramPacket(array, array.length, sin, port); - - try { - soc.send(pac, new_ttl); - } catch(java.io.IOException e) { - ttl = soc.getTTL(); - soc.close(); - if(ttl != old_ttl) - throw new RuntimeException("TTL "); - } - soc.close(); - } -} diff --git a/test/jdk/java/net/MulticastSocket/SendPortZero.java b/test/jdk/java/net/MulticastSocket/SendPortZero.java index 2155cf4149f..0d8acd86c8c 100644 --- a/test/jdk/java/net/MulticastSocket/SendPortZero.java +++ b/test/jdk/java/net/MulticastSocket/SendPortZero.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,7 +93,6 @@ public Object[][] variants() { @Test(dataProvider = "data") public void testSend(MulticastSocket ms, DatagramPacket pkt) { assertThrows(SE, () -> ms.send(pkt)); - assertThrows(SE, () -> ms.send(pkt, (byte) 0)); } @AfterTest diff --git a/test/jdk/java/net/MulticastSocket/SetLoopbackOption.java b/test/jdk/java/net/MulticastSocket/SetLoopbackOption.java index 7e39e6fc013..ed831cfbdf7 100644 --- a/test/jdk/java/net/MulticastSocket/SetLoopbackOption.java +++ b/test/jdk/java/net/MulticastSocket/SetLoopbackOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -206,16 +206,6 @@ protected void receive(DatagramPacket p) throws IOException { shouldNotComeHere(); } - @Override - protected void setTTL(byte ttl) throws IOException { - shouldNotComeHere(); - } - - @Override - protected byte getTTL() throws IOException { - return shouldNotComeHere(); - } - @Override protected void setTimeToLive(int ttl) throws IOException { shouldNotComeHere(); diff --git a/test/jdk/java/net/MulticastSocket/SetTTLAndGetTTL.java b/test/jdk/java/net/MulticastSocket/SetTTLAndGetTTL.java deleted file mode 100644 index ba07dc57dfd..00000000000 --- a/test/jdk/java/net/MulticastSocket/SetTTLAndGetTTL.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* @test - * @bug 4189640 - * @summary Make setTTL/getTTL works - * @run main SetTTLAndGetTTL - */ - -import java.net.*; - -public class SetTTLAndGetTTL { - - public static void main(String args[]) throws Exception { - MulticastSocket soc = null; - - try { - soc = new MulticastSocket(); - } catch(Exception e) { - throw new Exception("Unexpected Exception"); - } - - soc.setTTL((byte)200); - byte ttlValue = soc.getTTL(); - if (ttlValue != (byte)200) - throw new Exception("setTTL/getTTL is broken"); - } -} diff --git a/test/jdk/java/net/MulticastSocket/SetTTLTo0.java b/test/jdk/java/net/MulticastSocket/SetTTLTo0.java index 8bb4184081a..68dc8c43bc9 100644 --- a/test/jdk/java/net/MulticastSocket/SetTTLTo0.java +++ b/test/jdk/java/net/MulticastSocket/SetTTLTo0.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,6 @@ public static void main(String args[]) throws Exception { throw new Exception("Unexpected Exception"); } - soc.setTTL((byte)0); soc.setTimeToLive(0); } diff --git a/test/jdk/java/net/SocketOption/CachedImplOptions.java b/test/jdk/java/net/SocketOption/CachedImplOptions.java index ed2c2a9ebdf..955414559c2 100644 --- a/test/jdk/java/net/SocketOption/CachedImplOptions.java +++ b/test/jdk/java/net/SocketOption/CachedImplOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -124,8 +124,6 @@ static abstract class AbstractDatagramSocketImpl extends DatagramSocketImpl { @Override protected int peek(InetAddress i) { return 0; } @Override protected int peekData(DatagramPacket p) { return 0; } @Override protected void receive(DatagramPacket p) { } - @Override protected void setTTL(byte ttl) { } - @Override protected byte getTTL() { return 0; } @Override protected void setTimeToLive(int ttl) { } @Override protected int getTimeToLive() { return 0; } @Override protected void join(InetAddress inetaddr) { } diff --git a/test/jdk/java/net/SocketOption/ImmutableOptions.java b/test/jdk/java/net/SocketOption/ImmutableOptions.java index 4a2e4419f9d..f15734edddc 100644 --- a/test/jdk/java/net/SocketOption/ImmutableOptions.java +++ b/test/jdk/java/net/SocketOption/ImmutableOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -162,10 +162,6 @@ protected void send(DatagramPacket p) throws IOException { } protected void receive(DatagramPacket p) throws IOException { } - protected void setTTL(byte ttl) throws IOException { } - - protected byte getTTL() throws IOException { return 0; } - protected void setTimeToLive(int ttl) throws IOException { } protected int getTimeToLive() throws IOException { return 0; } diff --git a/test/jdk/java/nio/channels/DatagramChannel/AdaptorMulticasting.java b/test/jdk/java/nio/channels/DatagramChannel/AdaptorMulticasting.java index cab2bc76285..4cb9be7efe9 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/AdaptorMulticasting.java +++ b/test/jdk/java/nio/channels/DatagramChannel/AdaptorMulticasting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -327,39 +327,27 @@ static void testNetworkInterface(MulticastSocket s, } /** - * Test getTimeToLive/setTimeToLive/getTTL/getTTL and IP_MULTICAST_TTL socket + * Test getTimeToLive/setTimeToLive and IP_MULTICAST_TTL socket * option. */ static void testTimeToLive(MulticastSocket s) throws IOException { // should be 1 by default assertTrue(s.getTimeToLive() == 1); - assertTrue(s.getTTL() == 1); assertTrue(s.getOption(IP_MULTICAST_TTL) == 1); // setTimeToLive for (int ttl = 0; ttl <= 2; ttl++) { s.setTimeToLive(ttl); assertTrue(s.getTimeToLive() == ttl); - assertTrue(s.getTTL() == ttl); assertTrue(s.getOption(IP_MULTICAST_TTL) == ttl); } assertThrows(IllegalArgumentException.class, () -> s.setTimeToLive(-1)); - // setTTL - for (byte ttl = (byte) -2; ttl <= 2; ttl++) { - s.setTTL(ttl); - assertTrue(s.getTTL() == ttl); - int intValue = Byte.toUnsignedInt(ttl); - assertTrue(s.getTimeToLive() == intValue); - assertTrue(s.getOption(IP_MULTICAST_TTL) == intValue); - } - // setOption(IP_MULTICAST_TTL) for (int ttl = 0; ttl <= 2; ttl++) { s.setOption(IP_MULTICAST_TTL, ttl); assertTrue(s.getOption(IP_MULTICAST_TTL) == ttl); assertTrue(s.getTimeToLive() == ttl); - assertTrue(s.getTTL() == ttl); } // bad values for IP_MULTICAST_TTL @@ -419,7 +407,7 @@ static void testSendReceive(MulticastSocket s, InetAddress group) throws IOExcep // send message to multicast group DatagramPacket p = new DatagramPacket(message, message.length); p.setSocketAddress(target); - s.send(p, (byte) 1); + s.send(p); // receive message s.setSoTimeout(0); @@ -463,7 +451,7 @@ static void testSendNoReceive(MulticastSocket s, InetAddress group) throws IOExc // send datagram to multicast group DatagramPacket p = new DatagramPacket(message, message.length); p.setSocketAddress(target); - s.send(p, (byte) 1); + s.send(p); // datagram should not be received s.setSoTimeout(500); From a08208283bcfe395c9962c8de3ba19fdd8cab985 Mon Sep 17 00:00:00 2001 From: David Briemann Date: Tue, 17 Jun 2025 10:01:36 +0000 Subject: [PATCH 080/213] 8354650: [PPC64] Try to reduce register definitions Reviewed-by: mdoerr, sroy --- .../ppc/gc/shared/barrierSetAssembler_ppc.cpp | 4 +- src/hotspot/cpu/ppc/ppc.ad | 847 +++++++----------- src/hotspot/cpu/ppc/register_ppc.hpp | 6 +- src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp | 140 +-- src/hotspot/cpu/ppc/vmreg_ppc.cpp | 2 +- src/hotspot/cpu/ppc/vmreg_ppc.hpp | 14 +- src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp | 4 +- 7 files changed, 412 insertions(+), 605 deletions(-) diff --git a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp index 32a7011ac26..405ac4b2310 100644 --- a/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shared/barrierSetAssembler_ppc.cpp @@ -333,9 +333,9 @@ int SaveLiveRegisters::iterate_over_register_mask(IterationAction action, int of } } else if (vm_reg->is_ConditionRegister()) { // NOP. Conditions registers are covered by save_LR_CR - } else if (vm_reg->is_VectorSRegister()) { + } else if (vm_reg->is_VectorRegister()) { assert(SuperwordUseVSX, "or should not reach here"); - VectorSRegister vs_reg = vm_reg->as_VectorSRegister(); + VectorSRegister vs_reg = (vm_reg->as_VectorRegister()).to_vsr(); if (vs_reg->encoding() >= VSR32->encoding() && vs_reg->encoding() <= VSR51->encoding()) { reg_save_index += (2 + (reg_save_index & 1)); // 2 slots + alignment if needed diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 1504c977fc7..80a39610a4c 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -255,329 +255,168 @@ register %{ reg_def SR_PPR( SOC, SOC, Op_RegP, 5, SR_PPR->as_VMReg()); // v // ---------------------------- -// Vector-Scalar Registers +// Vector Registers // ---------------------------- - // 1st 32 VSRs are aliases for the FPRs which are already defined above. - reg_def VSR0 (SOC, SOC, Op_RegF, 0, VMRegImpl::Bad()); - reg_def VSR0_H (SOC, SOC, Op_RegF, 0, VMRegImpl::Bad()); - reg_def VSR0_J (SOC, SOC, Op_RegF, 0, VMRegImpl::Bad()); - reg_def VSR0_K (SOC, SOC, Op_RegF, 0, VMRegImpl::Bad()); - - reg_def VSR1 (SOC, SOC, Op_RegF, 1, VMRegImpl::Bad()); - reg_def VSR1_H (SOC, SOC, Op_RegF, 1, VMRegImpl::Bad()); - reg_def VSR1_J (SOC, SOC, Op_RegF, 1, VMRegImpl::Bad()); - reg_def VSR1_K (SOC, SOC, Op_RegF, 1, VMRegImpl::Bad()); - - reg_def VSR2 (SOC, SOC, Op_RegF, 2, VMRegImpl::Bad()); - reg_def VSR2_H (SOC, SOC, Op_RegF, 2, VMRegImpl::Bad()); - reg_def VSR2_J (SOC, SOC, Op_RegF, 2, VMRegImpl::Bad()); - reg_def VSR2_K (SOC, SOC, Op_RegF, 2, VMRegImpl::Bad()); - - reg_def VSR3 (SOC, SOC, Op_RegF, 3, VMRegImpl::Bad()); - reg_def VSR3_H (SOC, SOC, Op_RegF, 3, VMRegImpl::Bad()); - reg_def VSR3_J (SOC, SOC, Op_RegF, 3, VMRegImpl::Bad()); - reg_def VSR3_K (SOC, SOC, Op_RegF, 3, VMRegImpl::Bad()); - - reg_def VSR4 (SOC, SOC, Op_RegF, 4, VMRegImpl::Bad()); - reg_def VSR4_H (SOC, SOC, Op_RegF, 4, VMRegImpl::Bad()); - reg_def VSR4_J (SOC, SOC, Op_RegF, 4, VMRegImpl::Bad()); - reg_def VSR4_K (SOC, SOC, Op_RegF, 4, VMRegImpl::Bad()); - - reg_def VSR5 (SOC, SOC, Op_RegF, 5, VMRegImpl::Bad()); - reg_def VSR5_H (SOC, SOC, Op_RegF, 5, VMRegImpl::Bad()); - reg_def VSR5_J (SOC, SOC, Op_RegF, 5, VMRegImpl::Bad()); - reg_def VSR5_K (SOC, SOC, Op_RegF, 5, VMRegImpl::Bad()); - - reg_def VSR6 (SOC, SOC, Op_RegF, 6, VMRegImpl::Bad()); - reg_def VSR6_H (SOC, SOC, Op_RegF, 6, VMRegImpl::Bad()); - reg_def VSR6_J (SOC, SOC, Op_RegF, 6, VMRegImpl::Bad()); - reg_def VSR6_K (SOC, SOC, Op_RegF, 6, VMRegImpl::Bad()); - - reg_def VSR7 (SOC, SOC, Op_RegF, 7, VMRegImpl::Bad()); - reg_def VSR7_H (SOC, SOC, Op_RegF, 7, VMRegImpl::Bad()); - reg_def VSR7_J (SOC, SOC, Op_RegF, 7, VMRegImpl::Bad()); - reg_def VSR7_K (SOC, SOC, Op_RegF, 7, VMRegImpl::Bad()); - - reg_def VSR8 (SOC, SOC, Op_RegF, 8, VMRegImpl::Bad()); - reg_def VSR8_H (SOC, SOC, Op_RegF, 8, VMRegImpl::Bad()); - reg_def VSR8_J (SOC, SOC, Op_RegF, 8, VMRegImpl::Bad()); - reg_def VSR8_K (SOC, SOC, Op_RegF, 8, VMRegImpl::Bad()); - - reg_def VSR9 (SOC, SOC, Op_RegF, 9, VMRegImpl::Bad()); - reg_def VSR9_H (SOC, SOC, Op_RegF, 9, VMRegImpl::Bad()); - reg_def VSR9_J (SOC, SOC, Op_RegF, 9, VMRegImpl::Bad()); - reg_def VSR9_K (SOC, SOC, Op_RegF, 9, VMRegImpl::Bad()); - - reg_def VSR10 (SOC, SOC, Op_RegF, 10, VMRegImpl::Bad()); - reg_def VSR10_H(SOC, SOC, Op_RegF, 10, VMRegImpl::Bad()); - reg_def VSR10_J(SOC, SOC, Op_RegF, 10, VMRegImpl::Bad()); - reg_def VSR10_K(SOC, SOC, Op_RegF, 10, VMRegImpl::Bad()); - - reg_def VSR11 (SOC, SOC, Op_RegF, 11, VMRegImpl::Bad()); - reg_def VSR11_H(SOC, SOC, Op_RegF, 11, VMRegImpl::Bad()); - reg_def VSR11_J(SOC, SOC, Op_RegF, 11, VMRegImpl::Bad()); - reg_def VSR11_K(SOC, SOC, Op_RegF, 11, VMRegImpl::Bad()); - - reg_def VSR12 (SOC, SOC, Op_RegF, 12, VMRegImpl::Bad()); - reg_def VSR12_H(SOC, SOC, Op_RegF, 12, VMRegImpl::Bad()); - reg_def VSR12_J(SOC, SOC, Op_RegF, 12, VMRegImpl::Bad()); - reg_def VSR12_K(SOC, SOC, Op_RegF, 12, VMRegImpl::Bad()); - - reg_def VSR13 (SOC, SOC, Op_RegF, 13, VMRegImpl::Bad()); - reg_def VSR13_H(SOC, SOC, Op_RegF, 13, VMRegImpl::Bad()); - reg_def VSR13_J(SOC, SOC, Op_RegF, 13, VMRegImpl::Bad()); - reg_def VSR13_K(SOC, SOC, Op_RegF, 13, VMRegImpl::Bad()); - - reg_def VSR14 (SOC, SOC, Op_RegF, 14, VMRegImpl::Bad()); - reg_def VSR14_H(SOC, SOC, Op_RegF, 14, VMRegImpl::Bad()); - reg_def VSR14_J(SOC, SOC, Op_RegF, 14, VMRegImpl::Bad()); - reg_def VSR14_K(SOC, SOC, Op_RegF, 14, VMRegImpl::Bad()); - - reg_def VSR15 (SOC, SOC, Op_RegF, 15, VMRegImpl::Bad()); - reg_def VSR15_H(SOC, SOC, Op_RegF, 15, VMRegImpl::Bad()); - reg_def VSR15_J(SOC, SOC, Op_RegF, 15, VMRegImpl::Bad()); - reg_def VSR15_K(SOC, SOC, Op_RegF, 15, VMRegImpl::Bad()); - - reg_def VSR16 (SOC, SOC, Op_RegF, 16, VMRegImpl::Bad()); - reg_def VSR16_H(SOC, SOC, Op_RegF, 16, VMRegImpl::Bad()); - reg_def VSR16_J(SOC, SOC, Op_RegF, 16, VMRegImpl::Bad()); - reg_def VSR16_K(SOC, SOC, Op_RegF, 16, VMRegImpl::Bad()); - - reg_def VSR17 (SOC, SOC, Op_RegF, 17, VMRegImpl::Bad()); - reg_def VSR17_H(SOC, SOC, Op_RegF, 17, VMRegImpl::Bad()); - reg_def VSR17_J(SOC, SOC, Op_RegF, 17, VMRegImpl::Bad()); - reg_def VSR17_K(SOC, SOC, Op_RegF, 17, VMRegImpl::Bad()); - - reg_def VSR18 (SOC, SOC, Op_RegF, 18, VMRegImpl::Bad()); - reg_def VSR18_H(SOC, SOC, Op_RegF, 18, VMRegImpl::Bad()); - reg_def VSR18_J(SOC, SOC, Op_RegF, 18, VMRegImpl::Bad()); - reg_def VSR18_K(SOC, SOC, Op_RegF, 18, VMRegImpl::Bad()); - - reg_def VSR19 (SOC, SOC, Op_RegF, 19, VMRegImpl::Bad()); - reg_def VSR19_H(SOC, SOC, Op_RegF, 19, VMRegImpl::Bad()); - reg_def VSR19_J(SOC, SOC, Op_RegF, 19, VMRegImpl::Bad()); - reg_def VSR19_K(SOC, SOC, Op_RegF, 19, VMRegImpl::Bad()); - - reg_def VSR20 (SOC, SOC, Op_RegF, 20, VMRegImpl::Bad()); - reg_def VSR20_H(SOC, SOC, Op_RegF, 20, VMRegImpl::Bad()); - reg_def VSR20_J(SOC, SOC, Op_RegF, 20, VMRegImpl::Bad()); - reg_def VSR20_K(SOC, SOC, Op_RegF, 20, VMRegImpl::Bad()); - - reg_def VSR21 (SOC, SOC, Op_RegF, 21, VMRegImpl::Bad()); - reg_def VSR21_H(SOC, SOC, Op_RegF, 21, VMRegImpl::Bad()); - reg_def VSR21_J(SOC, SOC, Op_RegF, 21, VMRegImpl::Bad()); - reg_def VSR21_K(SOC, SOC, Op_RegF, 21, VMRegImpl::Bad()); - - reg_def VSR22 (SOC, SOC, Op_RegF, 22, VMRegImpl::Bad()); - reg_def VSR22_H(SOC, SOC, Op_RegF, 22, VMRegImpl::Bad()); - reg_def VSR22_J(SOC, SOC, Op_RegF, 22, VMRegImpl::Bad()); - reg_def VSR22_K(SOC, SOC, Op_RegF, 22, VMRegImpl::Bad()); - - reg_def VSR23 (SOC, SOC, Op_RegF, 23, VMRegImpl::Bad()); - reg_def VSR23_H(SOC, SOC, Op_RegF, 23, VMRegImpl::Bad()); - reg_def VSR23_J(SOC, SOC, Op_RegF, 23, VMRegImpl::Bad()); - reg_def VSR23_K(SOC, SOC, Op_RegF, 23, VMRegImpl::Bad()); - - reg_def VSR24 (SOC, SOC, Op_RegF, 24, VMRegImpl::Bad()); - reg_def VSR24_H(SOC, SOC, Op_RegF, 24, VMRegImpl::Bad()); - reg_def VSR24_J(SOC, SOC, Op_RegF, 24, VMRegImpl::Bad()); - reg_def VSR24_K(SOC, SOC, Op_RegF, 24, VMRegImpl::Bad()); - - reg_def VSR25 (SOC, SOC, Op_RegF, 25, VMRegImpl::Bad()); - reg_def VSR25_H(SOC, SOC, Op_RegF, 25, VMRegImpl::Bad()); - reg_def VSR25_J(SOC, SOC, Op_RegF, 25, VMRegImpl::Bad()); - reg_def VSR25_K(SOC, SOC, Op_RegF, 25, VMRegImpl::Bad()); - - reg_def VSR26 (SOC, SOC, Op_RegF, 26, VMRegImpl::Bad()); - reg_def VSR26_H(SOC, SOC, Op_RegF, 26, VMRegImpl::Bad()); - reg_def VSR26_J(SOC, SOC, Op_RegF, 26, VMRegImpl::Bad()); - reg_def VSR26_K(SOC, SOC, Op_RegF, 26, VMRegImpl::Bad()); - - reg_def VSR27 (SOC, SOC, Op_RegF, 27, VMRegImpl::Bad()); - reg_def VSR27_H(SOC, SOC, Op_RegF, 27, VMRegImpl::Bad()); - reg_def VSR27_J(SOC, SOC, Op_RegF, 27, VMRegImpl::Bad()); - reg_def VSR27_K(SOC, SOC, Op_RegF, 27, VMRegImpl::Bad()); - - reg_def VSR28 (SOC, SOC, Op_RegF, 28, VMRegImpl::Bad()); - reg_def VSR28_H(SOC, SOC, Op_RegF, 28, VMRegImpl::Bad()); - reg_def VSR28_J(SOC, SOC, Op_RegF, 28, VMRegImpl::Bad()); - reg_def VSR28_K(SOC, SOC, Op_RegF, 28, VMRegImpl::Bad()); - - reg_def VSR29 (SOC, SOC, Op_RegF, 29, VMRegImpl::Bad()); - reg_def VSR29_H(SOC, SOC, Op_RegF, 29, VMRegImpl::Bad()); - reg_def VSR29_J(SOC, SOC, Op_RegF, 29, VMRegImpl::Bad()); - reg_def VSR29_K(SOC, SOC, Op_RegF, 29, VMRegImpl::Bad()); - - reg_def VSR30 (SOC, SOC, Op_RegF, 30, VMRegImpl::Bad()); - reg_def VSR30_H(SOC, SOC, Op_RegF, 30, VMRegImpl::Bad()); - reg_def VSR30_J(SOC, SOC, Op_RegF, 30, VMRegImpl::Bad()); - reg_def VSR30_K(SOC, SOC, Op_RegF, 30, VMRegImpl::Bad()); - - reg_def VSR31 (SOC, SOC, Op_RegF, 31, VMRegImpl::Bad()); - reg_def VSR31_H(SOC, SOC, Op_RegF, 31, VMRegImpl::Bad()); - reg_def VSR31_J(SOC, SOC, Op_RegF, 31, VMRegImpl::Bad()); - reg_def VSR31_K(SOC, SOC, Op_RegF, 31, VMRegImpl::Bad()); - - // 2nd 32 VSRs are aliases for the VRs which are only defined here. - reg_def VSR32 (SOC, SOC, Op_RegF, 32, VSR32->as_VMReg() ); - reg_def VSR32_H(SOC, SOC, Op_RegF, 32, VSR32->as_VMReg()->next() ); - reg_def VSR32_J(SOC, SOC, Op_RegF, 32, VSR32->as_VMReg()->next(2)); - reg_def VSR32_K(SOC, SOC, Op_RegF, 32, VSR32->as_VMReg()->next(3)); - - reg_def VSR33 (SOC, SOC, Op_RegF, 33, VSR33->as_VMReg() ); - reg_def VSR33_H(SOC, SOC, Op_RegF, 33, VSR33->as_VMReg()->next() ); - reg_def VSR33_J(SOC, SOC, Op_RegF, 33, VSR33->as_VMReg()->next(2)); - reg_def VSR33_K(SOC, SOC, Op_RegF, 33, VSR33->as_VMReg()->next(3)); - - reg_def VSR34 (SOC, SOC, Op_RegF, 34, VSR34->as_VMReg() ); - reg_def VSR34_H(SOC, SOC, Op_RegF, 34, VSR34->as_VMReg()->next() ); - reg_def VSR34_J(SOC, SOC, Op_RegF, 34, VSR34->as_VMReg()->next(2)); - reg_def VSR34_K(SOC, SOC, Op_RegF, 34, VSR34->as_VMReg()->next(3)); - - reg_def VSR35 (SOC, SOC, Op_RegF, 35, VSR35->as_VMReg() ); - reg_def VSR35_H(SOC, SOC, Op_RegF, 35, VSR35->as_VMReg()->next() ); - reg_def VSR35_J(SOC, SOC, Op_RegF, 35, VSR35->as_VMReg()->next(2)); - reg_def VSR35_K(SOC, SOC, Op_RegF, 35, VSR35->as_VMReg()->next(3)); - - reg_def VSR36 (SOC, SOC, Op_RegF, 36, VSR36->as_VMReg() ); - reg_def VSR36_H(SOC, SOC, Op_RegF, 36, VSR36->as_VMReg()->next() ); - reg_def VSR36_J(SOC, SOC, Op_RegF, 36, VSR36->as_VMReg()->next(2)); - reg_def VSR36_K(SOC, SOC, Op_RegF, 36, VSR36->as_VMReg()->next(3)); - - reg_def VSR37 (SOC, SOC, Op_RegF, 37, VSR37->as_VMReg() ); - reg_def VSR37_H(SOC, SOC, Op_RegF, 37, VSR37->as_VMReg()->next() ); - reg_def VSR37_J(SOC, SOC, Op_RegF, 37, VSR37->as_VMReg()->next(2)); - reg_def VSR37_K(SOC, SOC, Op_RegF, 37, VSR37->as_VMReg()->next(3)); - - reg_def VSR38 (SOC, SOC, Op_RegF, 38, VSR38->as_VMReg() ); - reg_def VSR38_H(SOC, SOC, Op_RegF, 38, VSR38->as_VMReg()->next() ); - reg_def VSR38_J(SOC, SOC, Op_RegF, 38, VSR38->as_VMReg()->next(2)); - reg_def VSR38_K(SOC, SOC, Op_RegF, 38, VSR38->as_VMReg()->next(3)); - - reg_def VSR39 (SOC, SOC, Op_RegF, 39, VSR39->as_VMReg() ); - reg_def VSR39_H(SOC, SOC, Op_RegF, 39, VSR39->as_VMReg()->next() ); - reg_def VSR39_J(SOC, SOC, Op_RegF, 39, VSR39->as_VMReg()->next(2)); - reg_def VSR39_K(SOC, SOC, Op_RegF, 39, VSR39->as_VMReg()->next(3)); - - reg_def VSR40 (SOC, SOC, Op_RegF, 40, VSR40->as_VMReg() ); - reg_def VSR40_H(SOC, SOC, Op_RegF, 40, VSR40->as_VMReg()->next() ); - reg_def VSR40_J(SOC, SOC, Op_RegF, 40, VSR40->as_VMReg()->next(2)); - reg_def VSR40_K(SOC, SOC, Op_RegF, 40, VSR40->as_VMReg()->next(3)); - - reg_def VSR41 (SOC, SOC, Op_RegF, 41, VSR41->as_VMReg() ); - reg_def VSR41_H(SOC, SOC, Op_RegF, 41, VSR41->as_VMReg()->next() ); - reg_def VSR41_J(SOC, SOC, Op_RegF, 41, VSR41->as_VMReg()->next(2)); - reg_def VSR41_K(SOC, SOC, Op_RegF, 41, VSR41->as_VMReg()->next(3)); - - reg_def VSR42 (SOC, SOC, Op_RegF, 42, VSR42->as_VMReg() ); - reg_def VSR42_H(SOC, SOC, Op_RegF, 42, VSR42->as_VMReg()->next() ); - reg_def VSR42_J(SOC, SOC, Op_RegF, 42, VSR42->as_VMReg()->next(2)); - reg_def VSR42_K(SOC, SOC, Op_RegF, 42, VSR42->as_VMReg()->next(3)); - - reg_def VSR43 (SOC, SOC, Op_RegF, 43, VSR43->as_VMReg() ); - reg_def VSR43_H(SOC, SOC, Op_RegF, 43, VSR43->as_VMReg()->next() ); - reg_def VSR43_J(SOC, SOC, Op_RegF, 43, VSR43->as_VMReg()->next(2)); - reg_def VSR43_K(SOC, SOC, Op_RegF, 43, VSR43->as_VMReg()->next(3)); - - reg_def VSR44 (SOC, SOC, Op_RegF, 44, VSR44->as_VMReg() ); - reg_def VSR44_H(SOC, SOC, Op_RegF, 44, VSR44->as_VMReg()->next() ); - reg_def VSR44_J(SOC, SOC, Op_RegF, 44, VSR44->as_VMReg()->next(2)); - reg_def VSR44_K(SOC, SOC, Op_RegF, 44, VSR44->as_VMReg()->next(3)); - - reg_def VSR45 (SOC, SOC, Op_RegF, 45, VSR45->as_VMReg() ); - reg_def VSR45_H(SOC, SOC, Op_RegF, 45, VSR45->as_VMReg()->next() ); - reg_def VSR45_J(SOC, SOC, Op_RegF, 45, VSR45->as_VMReg()->next(2)); - reg_def VSR45_K(SOC, SOC, Op_RegF, 45, VSR45->as_VMReg()->next(3)); - - reg_def VSR46 (SOC, SOC, Op_RegF, 46, VSR46->as_VMReg() ); - reg_def VSR46_H(SOC, SOC, Op_RegF, 46, VSR46->as_VMReg()->next() ); - reg_def VSR46_J(SOC, SOC, Op_RegF, 46, VSR46->as_VMReg()->next(2)); - reg_def VSR46_K(SOC, SOC, Op_RegF, 46, VSR46->as_VMReg()->next(3)); - - reg_def VSR47 (SOC, SOC, Op_RegF, 47, VSR47->as_VMReg() ); - reg_def VSR47_H(SOC, SOC, Op_RegF, 47, VSR47->as_VMReg()->next() ); - reg_def VSR47_J(SOC, SOC, Op_RegF, 47, VSR47->as_VMReg()->next(2)); - reg_def VSR47_K(SOC, SOC, Op_RegF, 47, VSR47->as_VMReg()->next(3)); - - reg_def VSR48 (SOC, SOC, Op_RegF, 48, VSR48->as_VMReg() ); - reg_def VSR48_H(SOC, SOC, Op_RegF, 48, VSR48->as_VMReg()->next() ); - reg_def VSR48_J(SOC, SOC, Op_RegF, 48, VSR48->as_VMReg()->next(2)); - reg_def VSR48_K(SOC, SOC, Op_RegF, 48, VSR48->as_VMReg()->next(3)); - - reg_def VSR49 (SOC, SOC, Op_RegF, 49, VSR49->as_VMReg() ); - reg_def VSR49_H(SOC, SOC, Op_RegF, 49, VSR49->as_VMReg()->next() ); - reg_def VSR49_J(SOC, SOC, Op_RegF, 49, VSR49->as_VMReg()->next(2)); - reg_def VSR49_K(SOC, SOC, Op_RegF, 49, VSR49->as_VMReg()->next(3)); - - reg_def VSR50 (SOC, SOC, Op_RegF, 50, VSR50->as_VMReg() ); - reg_def VSR50_H(SOC, SOC, Op_RegF, 50, VSR50->as_VMReg()->next() ); - reg_def VSR50_J(SOC, SOC, Op_RegF, 50, VSR50->as_VMReg()->next(2)); - reg_def VSR50_K(SOC, SOC, Op_RegF, 50, VSR50->as_VMReg()->next(3)); - - reg_def VSR51 (SOC, SOC, Op_RegF, 51, VSR51->as_VMReg() ); - reg_def VSR51_H(SOC, SOC, Op_RegF, 51, VSR51->as_VMReg()->next() ); - reg_def VSR51_J(SOC, SOC, Op_RegF, 51, VSR51->as_VMReg()->next(2)); - reg_def VSR51_K(SOC, SOC, Op_RegF, 51, VSR51->as_VMReg()->next(3)); - - reg_def VSR52 (SOC, SOE, Op_RegF, 52, VSR52->as_VMReg() ); - reg_def VSR52_H(SOC, SOE, Op_RegF, 52, VSR52->as_VMReg()->next() ); - reg_def VSR52_J(SOC, SOE, Op_RegF, 52, VSR52->as_VMReg()->next(2)); - reg_def VSR52_K(SOC, SOE, Op_RegF, 52, VSR52->as_VMReg()->next(3)); - - reg_def VSR53 (SOC, SOE, Op_RegF, 53, VSR53->as_VMReg() ); - reg_def VSR53_H(SOC, SOE, Op_RegF, 53, VSR53->as_VMReg()->next() ); - reg_def VSR53_J(SOC, SOE, Op_RegF, 53, VSR53->as_VMReg()->next(2)); - reg_def VSR53_K(SOC, SOE, Op_RegF, 53, VSR53->as_VMReg()->next(3)); - - reg_def VSR54 (SOC, SOE, Op_RegF, 54, VSR54->as_VMReg() ); - reg_def VSR54_H(SOC, SOE, Op_RegF, 54, VSR54->as_VMReg()->next() ); - reg_def VSR54_J(SOC, SOE, Op_RegF, 54, VSR54->as_VMReg()->next(2)); - reg_def VSR54_K(SOC, SOE, Op_RegF, 54, VSR54->as_VMReg()->next(3)); - - reg_def VSR55 (SOC, SOE, Op_RegF, 55, VSR55->as_VMReg() ); - reg_def VSR55_H(SOC, SOE, Op_RegF, 55, VSR55->as_VMReg()->next() ); - reg_def VSR55_J(SOC, SOE, Op_RegF, 55, VSR55->as_VMReg()->next(2)); - reg_def VSR55_K(SOC, SOE, Op_RegF, 55, VSR55->as_VMReg()->next(3)); - - reg_def VSR56 (SOC, SOE, Op_RegF, 56, VSR56->as_VMReg() ); - reg_def VSR56_H(SOC, SOE, Op_RegF, 56, VSR56->as_VMReg()->next() ); - reg_def VSR56_J(SOC, SOE, Op_RegF, 56, VSR56->as_VMReg()->next(2)); - reg_def VSR56_K(SOC, SOE, Op_RegF, 56, VSR56->as_VMReg()->next(3)); - - reg_def VSR57 (SOC, SOE, Op_RegF, 57, VSR57->as_VMReg() ); - reg_def VSR57_H(SOC, SOE, Op_RegF, 57, VSR57->as_VMReg()->next() ); - reg_def VSR57_J(SOC, SOE, Op_RegF, 57, VSR57->as_VMReg()->next(2)); - reg_def VSR57_K(SOC, SOE, Op_RegF, 57, VSR57->as_VMReg()->next(3)); - - reg_def VSR58 (SOC, SOE, Op_RegF, 58, VSR58->as_VMReg() ); - reg_def VSR58_H(SOC, SOE, Op_RegF, 58, VSR58->as_VMReg()->next() ); - reg_def VSR58_J(SOC, SOE, Op_RegF, 58, VSR58->as_VMReg()->next(2)); - reg_def VSR58_K(SOC, SOE, Op_RegF, 58, VSR58->as_VMReg()->next(3)); - - reg_def VSR59 (SOC, SOE, Op_RegF, 59, VSR59->as_VMReg() ); - reg_def VSR59_H(SOC, SOE, Op_RegF, 59, VSR59->as_VMReg()->next() ); - reg_def VSR59_J(SOC, SOE, Op_RegF, 59, VSR59->as_VMReg()->next(2)); - reg_def VSR59_K(SOC, SOE, Op_RegF, 59, VSR59->as_VMReg()->next(3)); - - reg_def VSR60 (SOC, SOE, Op_RegF, 60, VSR60->as_VMReg() ); - reg_def VSR60_H(SOC, SOE, Op_RegF, 60, VSR60->as_VMReg()->next() ); - reg_def VSR60_J(SOC, SOE, Op_RegF, 60, VSR60->as_VMReg()->next(2)); - reg_def VSR60_K(SOC, SOE, Op_RegF, 60, VSR60->as_VMReg()->next(3)); - - reg_def VSR61 (SOC, SOE, Op_RegF, 61, VSR61->as_VMReg() ); - reg_def VSR61_H(SOC, SOE, Op_RegF, 61, VSR61->as_VMReg()->next() ); - reg_def VSR61_J(SOC, SOE, Op_RegF, 61, VSR61->as_VMReg()->next(2)); - reg_def VSR61_K(SOC, SOE, Op_RegF, 61, VSR61->as_VMReg()->next(3)); - - reg_def VSR62 (SOC, SOE, Op_RegF, 62, VSR62->as_VMReg() ); - reg_def VSR62_H(SOC, SOE, Op_RegF, 62, VSR62->as_VMReg()->next() ); - reg_def VSR62_J(SOC, SOE, Op_RegF, 62, VSR62->as_VMReg()->next(2)); - reg_def VSR62_K(SOC, SOE, Op_RegF, 62, VSR62->as_VMReg()->next(3)); - - reg_def VSR63 (SOC, SOE, Op_RegF, 63, VSR63->as_VMReg() ); - reg_def VSR63_H(SOC, SOE, Op_RegF, 63, VSR63->as_VMReg()->next() ); - reg_def VSR63_J(SOC, SOE, Op_RegF, 63, VSR63->as_VMReg()->next(2)); - reg_def VSR63_K(SOC, SOE, Op_RegF, 63, VSR63->as_VMReg()->next(3)); + + reg_def VR0 (SOC, SOC, Op_RegF, 0, VR0->as_VMReg() ); + reg_def VR0_H(SOC, SOC, Op_RegF, 0, VR0->as_VMReg()->next() ); + reg_def VR0_J(SOC, SOC, Op_RegF, 0, VR0->as_VMReg()->next(2)); + reg_def VR0_K(SOC, SOC, Op_RegF, 0, VR0->as_VMReg()->next(3)); + + reg_def VR1 (SOC, SOC, Op_RegF, 1, VR1->as_VMReg() ); + reg_def VR1_H(SOC, SOC, Op_RegF, 1, VR1->as_VMReg()->next() ); + reg_def VR1_J(SOC, SOC, Op_RegF, 1, VR1->as_VMReg()->next(2)); + reg_def VR1_K(SOC, SOC, Op_RegF, 1, VR1->as_VMReg()->next(3)); + + reg_def VR2 (SOC, SOC, Op_RegF, 2, VR2->as_VMReg() ); + reg_def VR2_H(SOC, SOC, Op_RegF, 2, VR2->as_VMReg()->next() ); + reg_def VR2_J(SOC, SOC, Op_RegF, 2, VR2->as_VMReg()->next(2)); + reg_def VR2_K(SOC, SOC, Op_RegF, 2, VR2->as_VMReg()->next(3)); + + reg_def VR3 (SOC, SOC, Op_RegF, 3, VR3->as_VMReg() ); + reg_def VR3_H(SOC, SOC, Op_RegF, 3, VR3->as_VMReg()->next() ); + reg_def VR3_J(SOC, SOC, Op_RegF, 3, VR3->as_VMReg()->next(2)); + reg_def VR3_K(SOC, SOC, Op_RegF, 3, VR3->as_VMReg()->next(3)); + + reg_def VR4 (SOC, SOC, Op_RegF, 4, VR4->as_VMReg() ); + reg_def VR4_H(SOC, SOC, Op_RegF, 4, VR4->as_VMReg()->next() ); + reg_def VR4_J(SOC, SOC, Op_RegF, 4, VR4->as_VMReg()->next(2)); + reg_def VR4_K(SOC, SOC, Op_RegF, 4, VR4->as_VMReg()->next(3)); + + reg_def VR5 (SOC, SOC, Op_RegF, 5, VR5->as_VMReg() ); + reg_def VR5_H(SOC, SOC, Op_RegF, 5, VR5->as_VMReg()->next() ); + reg_def VR5_J(SOC, SOC, Op_RegF, 5, VR5->as_VMReg()->next(2)); + reg_def VR5_K(SOC, SOC, Op_RegF, 5, VR5->as_VMReg()->next(3)); + + reg_def VR6 (SOC, SOC, Op_RegF, 6, VR6->as_VMReg() ); + reg_def VR6_H(SOC, SOC, Op_RegF, 6, VR6->as_VMReg()->next() ); + reg_def VR6_J(SOC, SOC, Op_RegF, 6, VR6->as_VMReg()->next(2)); + reg_def VR6_K(SOC, SOC, Op_RegF, 6, VR6->as_VMReg()->next(3)); + + reg_def VR7 (SOC, SOC, Op_RegF, 7, VR7->as_VMReg() ); + reg_def VR7_H(SOC, SOC, Op_RegF, 7, VR7->as_VMReg()->next() ); + reg_def VR7_J(SOC, SOC, Op_RegF, 7, VR7->as_VMReg()->next(2)); + reg_def VR7_K(SOC, SOC, Op_RegF, 7, VR7->as_VMReg()->next(3)); + + reg_def VR8 (SOC, SOC, Op_RegF, 8, VR8->as_VMReg() ); + reg_def VR8_H(SOC, SOC, Op_RegF, 8, VR8->as_VMReg()->next() ); + reg_def VR8_J(SOC, SOC, Op_RegF, 8, VR8->as_VMReg()->next(2)); + reg_def VR8_K(SOC, SOC, Op_RegF, 8, VR8->as_VMReg()->next(3)); + + reg_def VR9 (SOC, SOC, Op_RegF, 9, VR9->as_VMReg() ); + reg_def VR9_H(SOC, SOC, Op_RegF, 9, VR9->as_VMReg()->next() ); + reg_def VR9_J(SOC, SOC, Op_RegF, 9, VR9->as_VMReg()->next(2)); + reg_def VR9_K(SOC, SOC, Op_RegF, 9, VR9->as_VMReg()->next(3)); + + reg_def VR10 (SOC, SOC, Op_RegF, 10, VR10->as_VMReg() ); + reg_def VR10_H(SOC, SOC, Op_RegF, 10, VR10->as_VMReg()->next() ); + reg_def VR10_J(SOC, SOC, Op_RegF, 10, VR10->as_VMReg()->next(2)); + reg_def VR10_K(SOC, SOC, Op_RegF, 10, VR10->as_VMReg()->next(3)); + + reg_def VR11 (SOC, SOC, Op_RegF, 11, VR11->as_VMReg() ); + reg_def VR11_H(SOC, SOC, Op_RegF, 11, VR11->as_VMReg()->next() ); + reg_def VR11_J(SOC, SOC, Op_RegF, 11, VR11->as_VMReg()->next(2)); + reg_def VR11_K(SOC, SOC, Op_RegF, 11, VR11->as_VMReg()->next(3)); + + reg_def VR12 (SOC, SOC, Op_RegF, 12, VR12->as_VMReg() ); + reg_def VR12_H(SOC, SOC, Op_RegF, 12, VR12->as_VMReg()->next() ); + reg_def VR12_J(SOC, SOC, Op_RegF, 12, VR12->as_VMReg()->next(2)); + reg_def VR12_K(SOC, SOC, Op_RegF, 12, VR12->as_VMReg()->next(3)); + + reg_def VR13 (SOC, SOC, Op_RegF, 13, VR13->as_VMReg() ); + reg_def VR13_H(SOC, SOC, Op_RegF, 13, VR13->as_VMReg()->next() ); + reg_def VR13_J(SOC, SOC, Op_RegF, 13, VR13->as_VMReg()->next(2)); + reg_def VR13_K(SOC, SOC, Op_RegF, 13, VR13->as_VMReg()->next(3)); + + reg_def VR14 (SOC, SOC, Op_RegF, 14, VR14->as_VMReg() ); + reg_def VR14_H(SOC, SOC, Op_RegF, 14, VR14->as_VMReg()->next() ); + reg_def VR14_J(SOC, SOC, Op_RegF, 14, VR14->as_VMReg()->next(2)); + reg_def VR14_K(SOC, SOC, Op_RegF, 14, VR14->as_VMReg()->next(3)); + + reg_def VR15 (SOC, SOC, Op_RegF, 15, VR15->as_VMReg() ); + reg_def VR15_H(SOC, SOC, Op_RegF, 15, VR15->as_VMReg()->next() ); + reg_def VR15_J(SOC, SOC, Op_RegF, 15, VR15->as_VMReg()->next(2)); + reg_def VR15_K(SOC, SOC, Op_RegF, 15, VR15->as_VMReg()->next(3)); + + reg_def VR16 (SOC, SOC, Op_RegF, 16, VR16->as_VMReg() ); + reg_def VR16_H(SOC, SOC, Op_RegF, 16, VR16->as_VMReg()->next() ); + reg_def VR16_J(SOC, SOC, Op_RegF, 16, VR16->as_VMReg()->next(2)); + reg_def VR16_K(SOC, SOC, Op_RegF, 16, VR16->as_VMReg()->next(3)); + + reg_def VR17 (SOC, SOC, Op_RegF, 17, VR17->as_VMReg() ); + reg_def VR17_H(SOC, SOC, Op_RegF, 17, VR17->as_VMReg()->next() ); + reg_def VR17_J(SOC, SOC, Op_RegF, 17, VR17->as_VMReg()->next(2)); + reg_def VR17_K(SOC, SOC, Op_RegF, 17, VR17->as_VMReg()->next(3)); + + reg_def VR18 (SOC, SOC, Op_RegF, 18, VR18->as_VMReg() ); + reg_def VR18_H(SOC, SOC, Op_RegF, 18, VR18->as_VMReg()->next() ); + reg_def VR18_J(SOC, SOC, Op_RegF, 18, VR18->as_VMReg()->next(2)); + reg_def VR18_K(SOC, SOC, Op_RegF, 18, VR18->as_VMReg()->next(3)); + + reg_def VR19 (SOC, SOC, Op_RegF, 19, VR19->as_VMReg() ); + reg_def VR19_H(SOC, SOC, Op_RegF, 19, VR19->as_VMReg()->next() ); + reg_def VR19_J(SOC, SOC, Op_RegF, 19, VR19->as_VMReg()->next(2)); + reg_def VR19_K(SOC, SOC, Op_RegF, 19, VR19->as_VMReg()->next(3)); + + reg_def VR20 (SOC, SOE, Op_RegF, 20, VR20->as_VMReg() ); + reg_def VR20_H(SOC, SOE, Op_RegF, 20, VR20->as_VMReg()->next() ); + reg_def VR20_J(SOC, SOE, Op_RegF, 20, VR20->as_VMReg()->next(2)); + reg_def VR20_K(SOC, SOE, Op_RegF, 20, VR20->as_VMReg()->next(3)); + + reg_def VR21 (SOC, SOE, Op_RegF, 21, VR21->as_VMReg() ); + reg_def VR21_H(SOC, SOE, Op_RegF, 21, VR21->as_VMReg()->next() ); + reg_def VR21_J(SOC, SOE, Op_RegF, 21, VR21->as_VMReg()->next(2)); + reg_def VR21_K(SOC, SOE, Op_RegF, 21, VR21->as_VMReg()->next(3)); + + reg_def VR22 (SOC, SOE, Op_RegF, 22, VR22->as_VMReg() ); + reg_def VR22_H(SOC, SOE, Op_RegF, 22, VR22->as_VMReg()->next() ); + reg_def VR22_J(SOC, SOE, Op_RegF, 22, VR22->as_VMReg()->next(2)); + reg_def VR22_K(SOC, SOE, Op_RegF, 22, VR22->as_VMReg()->next(3)); + + reg_def VR23 (SOC, SOE, Op_RegF, 23, VR23->as_VMReg() ); + reg_def VR23_H(SOC, SOE, Op_RegF, 23, VR23->as_VMReg()->next() ); + reg_def VR23_J(SOC, SOE, Op_RegF, 23, VR23->as_VMReg()->next(2)); + reg_def VR23_K(SOC, SOE, Op_RegF, 23, VR23->as_VMReg()->next(3)); + + reg_def VR24 (SOC, SOE, Op_RegF, 24, VR24->as_VMReg() ); + reg_def VR24_H(SOC, SOE, Op_RegF, 24, VR24->as_VMReg()->next() ); + reg_def VR24_J(SOC, SOE, Op_RegF, 24, VR24->as_VMReg()->next(2)); + reg_def VR24_K(SOC, SOE, Op_RegF, 24, VR24->as_VMReg()->next(3)); + + reg_def VR25 (SOC, SOE, Op_RegF, 25, VR25->as_VMReg() ); + reg_def VR25_H(SOC, SOE, Op_RegF, 25, VR25->as_VMReg()->next() ); + reg_def VR25_J(SOC, SOE, Op_RegF, 25, VR25->as_VMReg()->next(2)); + reg_def VR25_K(SOC, SOE, Op_RegF, 25, VR25->as_VMReg()->next(3)); + + reg_def VR26 (SOC, SOE, Op_RegF, 26, VR26->as_VMReg() ); + reg_def VR26_H(SOC, SOE, Op_RegF, 26, VR26->as_VMReg()->next() ); + reg_def VR26_J(SOC, SOE, Op_RegF, 26, VR26->as_VMReg()->next(2)); + reg_def VR26_K(SOC, SOE, Op_RegF, 26, VR26->as_VMReg()->next(3)); + + reg_def VR27 (SOC, SOE, Op_RegF, 27, VR27->as_VMReg() ); + reg_def VR27_H(SOC, SOE, Op_RegF, 27, VR27->as_VMReg()->next() ); + reg_def VR27_J(SOC, SOE, Op_RegF, 27, VR27->as_VMReg()->next(2)); + reg_def VR27_K(SOC, SOE, Op_RegF, 27, VR27->as_VMReg()->next(3)); + + reg_def VR28 (SOC, SOE, Op_RegF, 28, VR28->as_VMReg() ); + reg_def VR28_H(SOC, SOE, Op_RegF, 28, VR28->as_VMReg()->next() ); + reg_def VR28_J(SOC, SOE, Op_RegF, 28, VR28->as_VMReg()->next(2)); + reg_def VR28_K(SOC, SOE, Op_RegF, 28, VR28->as_VMReg()->next(3)); + + reg_def VR29 (SOC, SOE, Op_RegF, 29, VR29->as_VMReg() ); + reg_def VR29_H(SOC, SOE, Op_RegF, 29, VR29->as_VMReg()->next() ); + reg_def VR29_J(SOC, SOE, Op_RegF, 29, VR29->as_VMReg()->next(2)); + reg_def VR29_K(SOC, SOE, Op_RegF, 29, VR29->as_VMReg()->next(3)); + + reg_def VR30 (SOC, SOE, Op_RegF, 30, VR30->as_VMReg() ); + reg_def VR30_H(SOC, SOE, Op_RegF, 30, VR30->as_VMReg()->next() ); + reg_def VR30_J(SOC, SOE, Op_RegF, 30, VR30->as_VMReg()->next(2)); + reg_def VR30_K(SOC, SOE, Op_RegF, 30, VR30->as_VMReg()->next(3)); + + reg_def VR31 (SOC, SOE, Op_RegF, 31, VR31->as_VMReg() ); + reg_def VR31_H(SOC, SOE, Op_RegF, 31, VR31->as_VMReg()->next() ); + reg_def VR31_J(SOC, SOE, Op_RegF, 31, VR31->as_VMReg()->next(2)); + reg_def VR31_K(SOC, SOE, Op_RegF, 31, VR31->as_VMReg()->next(3)); // ---------------------------- // Specify priority of register selection within phases of register @@ -696,70 +535,38 @@ alloc_class chunk1 ( ); alloc_class chunk2 ( - VSR0 , VSR0_H , VSR0_J , VSR0_K , - VSR1 , VSR1_H , VSR1_J , VSR1_K , - VSR2 , VSR2_H , VSR2_J , VSR2_K , - VSR3 , VSR3_H , VSR3_J , VSR3_K , - VSR4 , VSR4_H , VSR4_J , VSR4_K , - VSR5 , VSR5_H , VSR5_J , VSR5_K , - VSR6 , VSR6_H , VSR6_J , VSR6_K , - VSR7 , VSR7_H , VSR7_J , VSR7_K , - VSR8 , VSR8_H , VSR8_J , VSR8_K , - VSR9 , VSR9_H , VSR9_J , VSR9_K , - VSR10, VSR10_H, VSR10_J, VSR10_K, - VSR11, VSR11_H, VSR11_J, VSR11_K, - VSR12, VSR12_H, VSR12_J, VSR12_K, - VSR13, VSR13_H, VSR13_J, VSR13_K, - VSR14, VSR14_H, VSR14_J, VSR14_K, - VSR15, VSR15_H, VSR15_J, VSR15_K, - VSR16, VSR16_H, VSR16_J, VSR16_K, - VSR17, VSR17_H, VSR17_J, VSR17_K, - VSR18, VSR18_H, VSR18_J, VSR18_K, - VSR19, VSR19_H, VSR19_J, VSR19_K, - VSR20, VSR20_H, VSR20_J, VSR20_K, - VSR21, VSR21_H, VSR21_J, VSR21_K, - VSR22, VSR22_H, VSR22_J, VSR22_K, - VSR23, VSR23_H, VSR23_J, VSR23_K, - VSR24, VSR24_H, VSR24_J, VSR24_K, - VSR25, VSR25_H, VSR25_J, VSR25_K, - VSR26, VSR26_H, VSR26_J, VSR26_K, - VSR27, VSR27_H, VSR27_J, VSR27_K, - VSR28, VSR28_H, VSR28_J, VSR28_K, - VSR29, VSR29_H, VSR29_J, VSR29_K, - VSR30, VSR30_H, VSR30_J, VSR30_K, - VSR31, VSR31_H, VSR31_J, VSR31_K, - VSR32, VSR32_H, VSR32_J, VSR32_K, - VSR33, VSR33_H, VSR33_J, VSR33_K, - VSR34, VSR34_H, VSR34_J, VSR34_K, - VSR35, VSR35_H, VSR35_J, VSR35_K, - VSR36, VSR36_H, VSR36_J, VSR36_K, - VSR37, VSR37_H, VSR37_J, VSR37_K, - VSR38, VSR38_H, VSR38_J, VSR38_K, - VSR39, VSR39_H, VSR39_J, VSR39_K, - VSR40, VSR40_H, VSR40_J, VSR40_K, - VSR41, VSR41_H, VSR41_J, VSR41_K, - VSR42, VSR42_H, VSR42_J, VSR42_K, - VSR43, VSR43_H, VSR43_J, VSR43_K, - VSR44, VSR44_H, VSR44_J, VSR44_K, - VSR45, VSR45_H, VSR45_J, VSR45_K, - VSR46, VSR46_H, VSR46_J, VSR46_K, - VSR47, VSR47_H, VSR47_J, VSR47_K, - VSR48, VSR48_H, VSR48_J, VSR48_K, - VSR49, VSR49_H, VSR49_J, VSR49_K, - VSR50, VSR50_H, VSR50_J, VSR50_K, - VSR51, VSR51_H, VSR51_J, VSR51_K, - VSR52, VSR52_H, VSR52_J, VSR52_K, - VSR53, VSR53_H, VSR53_J, VSR53_K, - VSR54, VSR54_H, VSR54_J, VSR54_K, - VSR55, VSR55_H, VSR55_J, VSR55_K, - VSR56, VSR56_H, VSR56_J, VSR56_K, - VSR57, VSR57_H, VSR57_J, VSR57_K, - VSR58, VSR58_H, VSR58_J, VSR58_K, - VSR59, VSR59_H, VSR59_J, VSR59_K, - VSR60, VSR60_H, VSR60_J, VSR60_K, - VSR61, VSR61_H, VSR61_J, VSR61_K, - VSR62, VSR62_H, VSR62_J, VSR62_K, - VSR63, VSR63_H, VSR63_J, VSR63_K + VR0 , VR0_H , VR0_J , VR0_K , + VR1 , VR1_H , VR1_J , VR1_K , + VR2 , VR2_H , VR2_J , VR2_K , + VR3 , VR3_H , VR3_J , VR3_K , + VR4 , VR4_H , VR4_J , VR4_K , + VR5 , VR5_H , VR5_J , VR5_K , + VR6 , VR6_H , VR6_J , VR6_K , + VR7 , VR7_H , VR7_J , VR7_K , + VR8 , VR8_H , VR8_J , VR8_K , + VR9 , VR9_H , VR9_J , VR9_K , + VR10, VR10_H, VR10_J, VR10_K, + VR11, VR11_H, VR11_J, VR11_K, + VR12, VR12_H, VR12_J, VR12_K, + VR13, VR13_H, VR13_J, VR13_K, + VR14, VR14_H, VR14_J, VR14_K, + VR15, VR15_H, VR15_J, VR15_K, + VR16, VR16_H, VR16_J, VR16_K, + VR17, VR17_H, VR17_J, VR17_K, + VR18, VR18_H, VR18_J, VR18_K, + VR19, VR19_H, VR19_J, VR19_K, + VR20, VR20_H, VR20_J, VR20_K, + VR21, VR21_H, VR21_J, VR21_K, + VR22, VR22_H, VR22_J, VR22_K, + VR23, VR23_H, VR23_J, VR23_K, + VR24, VR24_H, VR24_J, VR24_K, + VR25, VR25_H, VR25_J, VR25_K, + VR26, VR26_H, VR26_J, VR26_K, + VR27, VR27_H, VR27_J, VR27_K, + VR28, VR28_H, VR28_J, VR28_K, + VR29, VR29_H, VR29_J, VR29_K, + VR30, VR30_H, VR30_J, VR30_K, + VR31, VR31_H, VR31_J, VR31_K ); alloc_class chunk3 ( @@ -1163,39 +970,39 @@ reg_class dbl_reg( // Vector-Scalar Register Class // ---------------------------- -reg_class vs_reg( - VSR32, VSR32_H, VSR32_J, VSR32_K, - VSR33, VSR33_H, VSR33_J, VSR33_K, - VSR34, VSR34_H, VSR34_J, VSR34_K, - VSR35, VSR35_H, VSR35_J, VSR35_K, - VSR36, VSR36_H, VSR36_J, VSR36_K, - VSR37, VSR37_H, VSR37_J, VSR37_K, - VSR38, VSR38_H, VSR38_J, VSR38_K, - VSR39, VSR39_H, VSR39_J, VSR39_K, - VSR40, VSR40_H, VSR40_J, VSR40_K, - VSR41, VSR41_H, VSR41_J, VSR41_K, - VSR42, VSR42_H, VSR42_J, VSR42_K, - VSR43, VSR43_H, VSR43_J, VSR43_K, - VSR44, VSR44_H, VSR44_J, VSR44_K, - VSR45, VSR45_H, VSR45_J, VSR45_K, - VSR46, VSR46_H, VSR46_J, VSR46_K, - VSR47, VSR47_H, VSR47_J, VSR47_K, - VSR48, VSR48_H, VSR48_J, VSR48_K, - VSR49, VSR49_H, VSR49_J, VSR49_K, - VSR50, VSR50_H, VSR50_J, VSR50_K, - VSR51, VSR51_H, VSR51_J, VSR51_K, - VSR52, VSR52_H, VSR52_J, VSR52_K, // non-volatile - VSR53, VSR53_H, VSR53_J, VSR53_K, // non-volatile - VSR54, VSR54_H, VSR54_J, VSR54_K, // non-volatile - VSR55, VSR55_H, VSR55_J, VSR55_K, // non-volatile - VSR56, VSR56_H, VSR56_J, VSR56_K, // non-volatile - VSR57, VSR57_H, VSR57_J, VSR57_K, // non-volatile - VSR58, VSR58_H, VSR58_J, VSR58_K, // non-volatile - VSR59, VSR59_H, VSR59_J, VSR59_K, // non-volatile - VSR60, VSR60_H, VSR60_J, VSR60_K, // non-volatile - VSR61, VSR61_H, VSR61_J, VSR61_K, // non-volatile - VSR62, VSR62_H, VSR62_J, VSR62_K, // non-volatile - VSR63, VSR63_H, VSR63_J, VSR63_K // non-volatile +reg_class v_reg( + VR0 , VR0_H , VR0_J , VR0_K , + VR1 , VR1_H , VR1_J , VR1_K , + VR2 , VR2_H , VR2_J , VR2_K , + VR3 , VR3_H , VR3_J , VR3_K , + VR4 , VR4_H , VR4_J , VR4_K , + VR5 , VR5_H , VR5_J , VR5_K , + VR6 , VR6_H , VR6_J , VR6_K , + VR7 , VR7_H , VR7_J , VR7_K , + VR8 , VR8_H , VR8_J , VR8_K , + VR9 , VR9_H , VR9_J , VR9_K , + VR10, VR10_H, VR10_J, VR10_K, + VR11, VR11_H, VR11_J, VR11_K, + VR12, VR12_H, VR12_J, VR12_K, + VR13, VR13_H, VR13_J, VR13_K, + VR14, VR14_H, VR14_J, VR14_K, + VR15, VR15_H, VR15_J, VR15_K, + VR16, VR16_H, VR16_J, VR16_K, + VR17, VR17_H, VR17_J, VR17_K, + VR18, VR18_H, VR18_J, VR18_K, + VR19, VR19_H, VR19_J, VR19_K, + VR20, VR20_H, VR20_J, VR20_K, + VR21, VR21_H, VR21_J, VR21_K, + VR22, VR22_H, VR22_J, VR22_K, + VR23, VR23_H, VR23_J, VR23_K, + VR24, VR24_H, VR24_J, VR24_K, + VR25, VR25_H, VR25_J, VR25_K, + VR26, VR26_H, VR26_J, VR26_K, + VR27, VR27_H, VR27_J, VR27_K, + VR28, VR28_H, VR28_J, VR28_K, + VR29, VR29_H, VR29_J, VR29_K, + VR30, VR30_H, VR30_J, VR30_K, + VR31, VR31_H, VR31_J, VR31_K ); %} @@ -1908,9 +1715,9 @@ const Pipeline * MachEpilogNode::pipeline() const { // ============================================================================= -// Figure out which register class each belongs in: rc_int, rc_float, rc_vs or +// Figure out which register class each belongs in: rc_int, rc_float, rc_vec or // rc_stack. -enum RC { rc_bad, rc_int, rc_float, rc_vs, rc_stack }; +enum RC { rc_bad, rc_int, rc_float, rc_vec, rc_stack }; static enum RC rc_class(OptoReg::Name reg) { // Return the register class for the given register. The given register @@ -1924,12 +1731,12 @@ static enum RC rc_class(OptoReg::Name reg) { if (reg < ConcreteRegisterImpl::max_gpr) return rc_int; // We have 64 floating-point register halves, starting at index 64. - STATIC_ASSERT((int)ConcreteRegisterImpl::max_fpr == (int)MachRegisterNumbers::VSR0_num); + STATIC_ASSERT((int)ConcreteRegisterImpl::max_fpr == (int)MachRegisterNumbers::VR0_num); if (reg < ConcreteRegisterImpl::max_fpr) return rc_float; // We have 64 vector-scalar registers, starting at index 128. - STATIC_ASSERT((int)ConcreteRegisterImpl::max_vsr == (int)MachRegisterNumbers::CR0_num); - if (reg < ConcreteRegisterImpl::max_vsr) return rc_vs; + STATIC_ASSERT((int)ConcreteRegisterImpl::max_vr == (int)MachRegisterNumbers::CR0_num); + if (reg < ConcreteRegisterImpl::max_vr) return rc_vec; // Condition and special purpose registers are not allocated. We only accept stack from here. assert(OptoReg::is_stack(reg), "what else is it?"); @@ -2005,9 +1812,9 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r } size += 16; } - // VectorSRegister->Memory Spill. - else if (src_lo_rc == rc_vs && dst_lo_rc == rc_stack) { - VectorSRegister Rsrc = as_VectorSRegister(Matcher::_regEncode[src_lo]); + // VectorRegister->Memory Spill. + else if (src_lo_rc == rc_vec && dst_lo_rc == rc_stack) { + VectorSRegister Rsrc = as_VectorRegister(Matcher::_regEncode[src_lo]).to_vsr(); int dst_offset = ra_->reg2offset(dst_lo); if (PowerArchitecturePPC64 >= 9) { if (is_aligned(dst_offset, 16)) { @@ -2032,9 +1839,9 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r size += 8; } } - // Memory->VectorSRegister Spill. - else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vs) { - VectorSRegister Rdst = as_VectorSRegister(Matcher::_regEncode[dst_lo]); + // Memory->VectorRegister Spill. + else if (src_lo_rc == rc_stack && dst_lo_rc == rc_vec) { + VectorSRegister Rdst = as_VectorRegister(Matcher::_regEncode[dst_lo]).to_vsr(); int src_offset = ra_->reg2offset(src_lo); if (PowerArchitecturePPC64 >= 9) { if (is_aligned(src_offset, 16)) { @@ -2057,17 +1864,17 @@ uint MachSpillCopyNode::implementation(C2_MacroAssembler *masm, PhaseRegAlloc *r size += 8; } } - // VectorSRegister->VectorSRegister. - else if (src_lo_rc == rc_vs && dst_lo_rc == rc_vs) { - VectorSRegister Rsrc = as_VectorSRegister(Matcher::_regEncode[src_lo]); - VectorSRegister Rdst = as_VectorSRegister(Matcher::_regEncode[dst_lo]); + // VectorRegister->VectorRegister. + else if (src_lo_rc == rc_vec && dst_lo_rc == rc_vec) { + VectorSRegister Rsrc = as_VectorRegister(Matcher::_regEncode[src_lo]).to_vsr(); + VectorSRegister Rdst = as_VectorRegister(Matcher::_regEncode[dst_lo]).to_vsr(); if (masm) { __ xxlor(Rdst, Rsrc, Rsrc); } size += 4; } else { - ShouldNotReachHere(); // No VSR spill. + ShouldNotReachHere(); // No VR spill. } return size; } @@ -4048,7 +3855,7 @@ ins_attrib ins_is_late_expanded_null_check_candidate(false); // Formats are generated automatically for constants and base registers. operand vecX() %{ - constraint(ALLOC_IN_RC(vs_reg)); + constraint(ALLOC_IN_RC(v_reg)); match(VecX); format %{ %} @@ -5624,7 +5431,7 @@ instruct loadV16_Power8(vecX dst, indirect mem) %{ format %{ "LXVD2X $dst, $mem \t// load 16-byte Vector" %} size(4); ins_encode %{ - __ lxvd2x($dst$$VectorSRegister, $mem$$Register); + __ lxvd2x($dst$$VectorRegister.to_vsr(), $mem$$Register); %} ins_pipe(pipe_class_default); %} @@ -5637,7 +5444,7 @@ instruct loadV16_Power9(vecX dst, memoryAlg16 mem) %{ format %{ "LXV $dst, $mem \t// load 16-byte Vector" %} size(4); ins_encode %{ - __ lxv($dst$$VectorSRegister, $mem$$disp, $mem$$Register); + __ lxv($dst$$VectorRegister.to_vsr(), $mem$$disp, $mem$$Register); %} ins_pipe(pipe_class_default); %} @@ -6664,7 +6471,7 @@ instruct storeV16_Power8(indirect mem, vecX src) %{ format %{ "STXVD2X $mem, $src \t// store 16-byte Vector" %} size(4); ins_encode %{ - __ stxvd2x($src$$VectorSRegister, $mem$$Register); + __ stxvd2x($src$$VectorRegister.to_vsr(), $mem$$Register); %} ins_pipe(pipe_class_default); %} @@ -6677,7 +6484,7 @@ instruct storeV16_Power9(memoryAlg16 mem, vecX src) %{ format %{ "STXV $mem, $src \t// store 16-byte Vector" %} size(4); ins_encode %{ - __ stxv($src$$VectorSRegister, $mem$$disp, $mem$$Register); + __ stxv($src$$VectorRegister.to_vsr(), $mem$$disp, $mem$$Register); %} ins_pipe(pipe_class_default); %} @@ -12634,9 +12441,9 @@ instruct bytes_reverse_int_vec(iRegIdst dst, iRegIsrc src, vecX tmpV) %{ "\tMFVSRWZ $dst, $tmpV" %} ins_encode %{ - __ mtvsrwz($tmpV$$VectorSRegister, $src$$Register); - __ xxbrw($tmpV$$VectorSRegister, $tmpV$$VectorSRegister); - __ mfvsrwz($dst$$Register, $tmpV$$VectorSRegister); + __ mtvsrwz($tmpV$$VectorRegister.to_vsr(), $src$$Register); + __ xxbrw($tmpV$$VectorRegister.to_vsr(), $tmpV$$VectorRegister->to_vsr()); + __ mfvsrwz($dst$$Register, $tmpV$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -12706,9 +12513,9 @@ instruct bytes_reverse_long_vec(iRegLdst dst, iRegLsrc src, vecX tmpV) %{ "\tMFVSRD $dst, $tmpV" %} ins_encode %{ - __ mtvsrd($tmpV$$VectorSRegister, $src$$Register); - __ xxbrd($tmpV$$VectorSRegister, $tmpV$$VectorSRegister); - __ mfvsrd($dst$$Register, $tmpV$$VectorSRegister); + __ mtvsrd($tmpV$$VectorRegister->to_vsr(), $src$$Register); + __ xxbrd($tmpV$$VectorRegister->to_vsr(), $tmpV$$VectorRegister->to_vsr()); + __ mfvsrd($dst$$Register, $tmpV$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -12947,7 +12754,7 @@ instruct mtvsrwz(vecX temp1, iRegIsrc src) %{ format %{ "MTVSRWZ $temp1, $src \t// Move to 16-byte register" %} size(4); ins_encode %{ - __ mtvsrwz($temp1$$VectorSRegister, $src$$Register); + __ mtvsrwz($temp1$$VectorRegister->to_vsr(), $src$$Register); %} ins_pipe(pipe_class_default); %} @@ -12958,7 +12765,7 @@ instruct xxspltw(vecX dst, vecX src, immI8 imm1) %{ format %{ "XXSPLTW $dst, $src, $imm1 \t// Splat word" %} size(4); ins_encode %{ - __ xxspltw($dst$$VectorSRegister, $src$$VectorSRegister, $imm1$$constant); + __ xxspltw($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr(), $imm1$$constant); %} ins_pipe(pipe_class_default); %} @@ -12969,7 +12776,7 @@ instruct xscvdpspn_regF(vecX dst, regF src) %{ format %{ "XSCVDPSPN $dst, $src \t// Convert scalar single precision to vector single precision" %} size(4); ins_encode %{ - __ xscvdpspn($dst$$VectorSRegister, $src$$FloatRegister->to_vsr()); + __ xscvdpspn($dst$$VectorRegister->to_vsr(), $src$$FloatRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13076,7 +12883,7 @@ instruct repl16B_immI0(vecX dst, immI_0 zero) %{ format %{ "XXLXOR $dst, $zero \t// replicate16B" %} size(4); ins_encode %{ - __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13089,7 +12896,7 @@ instruct repl16B_immIminus1(vecX dst, immI_minus1 src) %{ format %{ "XXLEQV $dst, $src \t// replicate16B" %} size(4); ins_encode %{ - __ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxleqv($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13154,7 +12961,7 @@ instruct repl8S_immI0(vecX dst, immI_0 zero) %{ format %{ "XXLXOR $dst, $zero \t// replicate8S" %} size(4); ins_encode %{ - __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13167,7 +12974,7 @@ instruct repl8S_immIminus1(vecX dst, immI_minus1 src) %{ format %{ "XXLEQV $dst, $src \t// replicate8S" %} size(4); ins_encode %{ - __ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxleqv($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13232,7 +13039,7 @@ instruct repl4I_immI0(vecX dst, immI_0 zero) %{ format %{ "XXLXOR $dst, $zero \t// replicate4I" %} size(4); ins_encode %{ - __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13245,7 +13052,7 @@ instruct repl4I_immIminus1(vecX dst, immI_minus1 src) %{ format %{ "XXLEQV $dst, $dst, $dst \t// replicate4I" %} size(4); ins_encode %{ - __ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxleqv($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13302,7 +13109,7 @@ instruct vadd16B_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VADDUBM $dst,$src1,$src2\t// add packed16B" %} size(4); ins_encode %{ - __ vaddubm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vaddubm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13313,7 +13120,7 @@ instruct vadd8S_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VADDUHM $dst,$src1,$src2\t// add packed8S" %} size(4); ins_encode %{ - __ vadduhm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vadduhm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13324,7 +13131,7 @@ instruct vadd4I_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VADDUWM $dst,$src1,$src2\t// add packed4I" %} size(4); ins_encode %{ - __ vadduwm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vadduwm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13335,7 +13142,7 @@ instruct vadd4F_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VADDFP $dst,$src1,$src2\t// add packed4F" %} size(4); ins_encode %{ - __ vaddfp($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vaddfp($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13346,7 +13153,7 @@ instruct vadd2L_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VADDUDM $dst,$src1,$src2\t// add packed2L" %} size(4); ins_encode %{ - __ vaddudm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vaddudm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13357,7 +13164,7 @@ instruct vadd2D_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "XVADDDP $dst,$src1,$src2\t// add packed2D" %} size(4); ins_encode %{ - __ xvadddp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvadddp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13370,7 +13177,7 @@ instruct vsub16B_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VSUBUBM $dst,$src1,$src2\t// sub packed16B" %} size(4); ins_encode %{ - __ vsububm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vsububm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13381,7 +13188,7 @@ instruct vsub8S_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VSUBUHM $dst,$src1,$src2\t// sub packed8S" %} size(4); ins_encode %{ - __ vsubuhm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vsubuhm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13392,7 +13199,7 @@ instruct vsub4I_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VSUBUWM $dst,$src1,$src2\t// sub packed4I" %} size(4); ins_encode %{ - __ vsubuwm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vsubuwm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13403,7 +13210,7 @@ instruct vsub4F_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VSUBFP $dst,$src1,$src2\t// sub packed4F" %} size(4); ins_encode %{ - __ vsubfp($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vsubfp($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13414,7 +13221,7 @@ instruct vsub2L_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VSUBUDM $dst,$src1,$src2\t// sub packed2L" %} size(4); ins_encode %{ - __ vsubudm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vsubudm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13425,7 +13232,7 @@ instruct vsub2D_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "XVSUBDP $dst,$src1,$src2\t// sub packed2D" %} size(4); ins_encode %{ - __ xvsubdp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvsubdp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13440,8 +13247,8 @@ instruct vmul8S_reg(vecX dst, vecX src1, vecX src2, vecX tmp) %{ format %{ "VMLADDUHM $dst,$src1,$src2\t// mul packed8S" %} size(8); ins_encode %{ - __ vspltish($tmp$$VectorSRegister->to_vr(), 0); - __ vmladduhm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr(), $tmp$$VectorSRegister->to_vr()); + __ vspltish($tmp$$VectorRegister, 0); + __ vmladduhm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister, $tmp$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13452,7 +13259,7 @@ instruct vmul4I_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "VMULUWM $dst,$src1,$src2\t// mul packed4I" %} size(4); ins_encode %{ - __ vmuluwm($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vmuluwm($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13463,7 +13270,7 @@ instruct vmul4F_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "XVMULSP $dst,$src1,$src2\t// mul packed4F" %} size(4); ins_encode %{ - __ xvmulsp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvmulsp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13474,7 +13281,7 @@ instruct vmul2D_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "XVMULDP $dst,$src1,$src2\t// mul packed2D" %} size(4); ins_encode %{ - __ xvmuldp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvmuldp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13487,7 +13294,7 @@ instruct vdiv4F_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "XVDIVSP $dst,$src1,$src2\t// div packed4F" %} size(4); ins_encode %{ - __ xvdivsp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvdivsp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13498,7 +13305,7 @@ instruct vdiv2D_reg(vecX dst, vecX src1, vecX src2) %{ format %{ "XVDIVDP $dst,$src1,$src2\t// div packed2D" %} size(4); ins_encode %{ - __ xvdivdp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvdivdp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13513,10 +13320,10 @@ instruct vmin_reg(vecX dst, vecX src1, vecX src2) %{ BasicType bt = Matcher::vector_element_basic_type(this); switch (bt) { case T_INT: - __ vminsw($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vminsw($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); break; case T_LONG: - __ vminsd($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vminsd($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); break; default: ShouldNotReachHere(); @@ -13533,10 +13340,10 @@ instruct vmax_reg(vecX dst, vecX src1, vecX src2) %{ BasicType bt = Matcher::vector_element_basic_type(this); switch (bt) { case T_INT: - __ vmaxsw($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vmaxsw($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); break; case T_LONG: - __ vmaxsd($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vmaxsd($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); break; default: ShouldNotReachHere(); @@ -13550,7 +13357,7 @@ instruct vand(vecX dst, vecX src1, vecX src2) %{ size(4); format %{ "VAND $dst,$src1,$src2\t// and vectors" %} ins_encode %{ - __ vand($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vand($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13560,7 +13367,7 @@ instruct vor(vecX dst, vecX src1, vecX src2) %{ size(4); format %{ "VOR $dst,$src1,$src2\t// or vectors" %} ins_encode %{ - __ vor($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vor($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13570,7 +13377,7 @@ instruct vxor(vecX dst, vecX src1, vecX src2) %{ size(4); format %{ "VXOR $dst,$src1,$src2\t// xor vectors" %} ins_encode %{ - __ vxor($dst$$VectorSRegister->to_vr(), $src1$$VectorSRegister->to_vr(), $src2$$VectorSRegister->to_vr()); + __ vxor($dst$$VectorRegister, $src1$$VectorRegister, $src2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13588,8 +13395,8 @@ instruct reductionI_arith_logic(iRegIdst dst, iRegIsrc srcInt, vecX srcVec, vecX size(24); ins_encode %{ int opcode = this->ideal_Opcode(); - __ reduceI(opcode, $dst$$Register, $srcInt$$Register, $srcVec$$VectorSRegister->to_vr(), - $tmp1$$VectorSRegister->to_vr(), $tmp2$$VectorSRegister->to_vr()); + __ reduceI(opcode, $dst$$Register, $srcInt$$Register, $srcVec$$VectorRegister, + $tmp1$$VectorRegister, $tmp2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13604,8 +13411,8 @@ instruct reductionI_min_max(iRegIdst dst, iRegIsrc srcInt, vecX srcVec, vecX tmp size(28); ins_encode %{ int opcode = this->ideal_Opcode(); - __ reduceI(opcode, $dst$$Register, $srcInt$$Register, $srcVec$$VectorSRegister->to_vr(), - $tmp1$$VectorSRegister->to_vr(), $tmp2$$VectorSRegister->to_vr()); + __ reduceI(opcode, $dst$$Register, $srcInt$$Register, $srcVec$$VectorRegister, + $tmp1$$VectorRegister, $tmp2$$VectorRegister); %} ins_pipe(pipe_class_default); %} @@ -13618,7 +13425,7 @@ instruct vabs4F_reg(vecX dst, vecX src) %{ format %{ "XVABSSP $dst,$src\t// absolute packed4F" %} size(4); ins_encode %{ - __ xvabssp($dst$$VectorSRegister, $src$$VectorSRegister); + __ xvabssp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13629,7 +13436,7 @@ instruct vabs2D_reg(vecX dst, vecX src) %{ format %{ "XVABSDP $dst,$src\t// absolute packed2D" %} size(4); ins_encode %{ - __ xvabsdp($dst$$VectorSRegister, $src$$VectorSRegister); + __ xvabsdp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13666,13 +13473,13 @@ instruct vround2D_reg(vecX dst, vecX src, immI8 rmode) %{ ins_encode %{ switch ($rmode$$constant) { case RoundDoubleModeNode::rmode_rint: - __ xvrdpic($dst$$VectorSRegister, $src$$VectorSRegister); + __ xvrdpic($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr()); break; case RoundDoubleModeNode::rmode_floor: - __ xvrdpim($dst$$VectorSRegister, $src$$VectorSRegister); + __ xvrdpim($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr()); break; case RoundDoubleModeNode::rmode_ceil: - __ xvrdpip($dst$$VectorSRegister, $src$$VectorSRegister); + __ xvrdpip($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr()); break; default: ShouldNotReachHere(); @@ -13689,7 +13496,7 @@ instruct vneg4F_reg(vecX dst, vecX src) %{ format %{ "XVNEGSP $dst,$src\t// negate packed4F" %} size(4); ins_encode %{ - __ xvnegsp($dst$$VectorSRegister, $src$$VectorSRegister); + __ xvnegsp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13700,7 +13507,7 @@ instruct vneg2D_reg(vecX dst, vecX src) %{ format %{ "XVNEGDP $dst,$src\t// negate packed2D" %} size(4); ins_encode %{ - __ xvnegdp($dst$$VectorSRegister, $src$$VectorSRegister); + __ xvnegdp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13713,7 +13520,7 @@ instruct vsqrt4F_reg(vecX dst, vecX src) %{ format %{ "XVSQRTSP $dst,$src\t// sqrt packed4F" %} size(4); ins_encode %{ - __ xvsqrtsp($dst$$VectorSRegister, $src$$VectorSRegister); + __ xvsqrtsp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13724,7 +13531,7 @@ instruct vsqrt2D_reg(vecX dst, vecX src) %{ format %{ "XVSQRTDP $dst,$src\t// sqrt packed2D" %} size(4); ins_encode %{ - __ xvsqrtdp($dst$$VectorSRegister, $src$$VectorSRegister); + __ xvsqrtdp($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13740,16 +13547,16 @@ instruct vpopcnt_reg(vecX dst, vecX src) %{ BasicType bt = Matcher::vector_element_basic_type(this); switch (bt) { case T_BYTE: - __ vpopcntb($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vpopcntb($dst$$VectorRegister, $src$$VectorRegister); break; case T_SHORT: - __ vpopcnth($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vpopcnth($dst$$VectorRegister, $src$$VectorRegister); break; case T_INT: - __ vpopcntw($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vpopcntw($dst$$VectorRegister, $src$$VectorRegister); break; case T_LONG: - __ vpopcntd($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vpopcntd($dst$$VectorRegister, $src$$VectorRegister); break; default: ShouldNotReachHere(); @@ -13766,16 +13573,16 @@ instruct vcount_leading_zeros_reg(vecX dst, vecX src) %{ BasicType bt = Matcher::vector_element_basic_type(this); switch (bt) { case T_BYTE: - __ vclzb($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vclzb($dst$$VectorRegister, $src$$VectorRegister); break; case T_SHORT: - __ vclzh($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vclzh($dst$$VectorRegister, $src$$VectorRegister); break; case T_INT: - __ vclzw($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vclzw($dst$$VectorRegister, $src$$VectorRegister); break; case T_LONG: - __ vclzd($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vclzd($dst$$VectorRegister, $src$$VectorRegister); break; default: ShouldNotReachHere(); @@ -13792,16 +13599,16 @@ instruct vcount_trailing_zeros_reg(vecX dst, vecX src) %{ BasicType bt = Matcher::vector_element_basic_type(this); switch (bt) { case T_BYTE: - __ vctzb($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vctzb($dst$$VectorRegister, $src$$VectorRegister); break; case T_SHORT: - __ vctzh($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vctzh($dst$$VectorRegister, $src$$VectorRegister); break; case T_INT: - __ vctzw($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vctzw($dst$$VectorRegister, $src$$VectorRegister); break; case T_LONG: - __ vctzd($dst$$VectorSRegister->to_vr(), $src$$VectorSRegister->to_vr()); + __ vctzd($dst$$VectorRegister, $src$$VectorRegister); break; default: ShouldNotReachHere(); @@ -13821,7 +13628,7 @@ instruct vfma4F(vecX dst, vecX src1, vecX src2) %{ size(4); ins_encode %{ assert(UseFMA, "Needs FMA instructions support."); - __ xvmaddasp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvmaddasp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13837,7 +13644,7 @@ instruct vfma4F_neg1(vecX dst, vecX src1, vecX src2) %{ size(4); ins_encode %{ assert(UseFMA, "Needs FMA instructions support."); - __ xvnmsubasp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvnmsubasp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13852,7 +13659,7 @@ instruct vfma4F_neg2(vecX dst, vecX src1, vecX src2) %{ size(4); ins_encode %{ assert(UseFMA, "Needs FMA instructions support."); - __ xvmsubasp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvmsubasp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13867,7 +13674,7 @@ instruct vfma2D(vecX dst, vecX src1, vecX src2) %{ size(4); ins_encode %{ assert(UseFMA, "Needs FMA instructions support."); - __ xvmaddadp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvmaddadp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13883,7 +13690,7 @@ instruct vfma2D_neg1(vecX dst, vecX src1, vecX src2) %{ size(4); ins_encode %{ assert(UseFMA, "Needs FMA instructions support."); - __ xvnmsubadp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvnmsubadp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13898,7 +13705,7 @@ instruct vfma2D_neg2(vecX dst, vecX src1, vecX src2) %{ size(4); ins_encode %{ assert(UseFMA, "Needs FMA instructions support."); - __ xvmsubadp($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister); + __ xvmsubadp($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -13993,7 +13800,7 @@ instruct repl4F_immF0(vecX dst, immF_0 zero) %{ format %{ "XXLXOR $dst, $zero \t// replicate4F" %} size(4); ins_encode %{ - __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -14006,7 +13813,7 @@ instruct repl2D_reg_Ex(vecX dst, regD src) %{ format %{ "XXPERMDI $dst, $src, $src, 0 \t// Splat doubleword" %} size(4); ins_encode %{ - __ xxpermdi($dst$$VectorSRegister, $src$$FloatRegister->to_vsr(), $src$$FloatRegister->to_vsr(), 0); + __ xxpermdi($dst$$VectorRegister->to_vsr(), $src$$FloatRegister->to_vsr(), $src$$FloatRegister->to_vsr(), 0); %} ins_pipe(pipe_class_default); %} @@ -14019,7 +13826,7 @@ instruct repl2D_immD0(vecX dst, immD_0 zero) %{ format %{ "XXLXOR $dst, $zero \t// replicate2D" %} size(4); ins_encode %{ - __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -14031,7 +13838,7 @@ instruct mtvsrd(vecX dst, iRegLsrc src) %{ format %{ "MTVSRD $dst, $src \t// Move to 16-byte register" %} size(4); ins_encode %{ - __ mtvsrd($dst$$VectorSRegister, $src$$Register); + __ mtvsrd($dst$$VectorRegister->to_vsr(), $src$$Register); %} ins_pipe(pipe_class_default); %} @@ -14042,7 +13849,7 @@ instruct xxspltd(vecX dst, vecX src, immI8 zero) %{ format %{ "XXSPLATD $dst, $src, $zero \t// Splat doubleword" %} size(4); ins_encode %{ - __ xxpermdi($dst$$VectorSRegister, $src$$VectorSRegister, $src$$VectorSRegister, $zero$$constant); + __ xxpermdi($dst$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr(), $src$$VectorRegister->to_vsr(), $zero$$constant); %} ins_pipe(pipe_class_default); %} @@ -14053,7 +13860,7 @@ instruct xxpermdi(vecX dst, vecX src1, vecX src2, immI8 zero) %{ format %{ "XXPERMDI $dst, $src1, $src2, $zero \t// Splat doubleword" %} size(4); ins_encode %{ - __ xxpermdi($dst$$VectorSRegister, $src1$$VectorSRegister, $src2$$VectorSRegister, $zero$$constant); + __ xxpermdi($dst$$VectorRegister->to_vsr(), $src1$$VectorRegister->to_vsr(), $src2$$VectorRegister->to_vsr(), $zero$$constant); %} ins_pipe(pipe_class_default); %} @@ -14078,7 +13885,7 @@ instruct repl2L_immI0(vecX dst, immI_0 zero) %{ format %{ "XXLXOR $dst, $zero \t// replicate2L" %} size(4); ins_encode %{ - __ xxlxor($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxlxor($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} @@ -14091,7 +13898,7 @@ instruct repl2L_immIminus1(vecX dst, immI_minus1 src) %{ format %{ "XXLEQV $dst, $src \t// replicate2L" %} size(4); ins_encode %{ - __ xxleqv($dst$$VectorSRegister, $dst$$VectorSRegister, $dst$$VectorSRegister); + __ xxleqv($dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr(), $dst$$VectorRegister->to_vsr()); %} ins_pipe(pipe_class_default); %} diff --git a/src/hotspot/cpu/ppc/register_ppc.hpp b/src/hotspot/cpu/ppc/register_ppc.hpp index b7949750dcc..2613d6c9822 100644 --- a/src/hotspot/cpu/ppc/register_ppc.hpp +++ b/src/hotspot/cpu/ppc/register_ppc.hpp @@ -321,6 +321,7 @@ class VectorRegister { // accessors constexpr int encoding() const { assert(is_valid(), "invalid register"); return _encoding; } + inline VMReg as_VMReg() const; // testers constexpr bool is_valid() const { return (0 <= _encoding && _encoding < number_of_registers); } @@ -392,7 +393,6 @@ class VectorSRegister { // accessors constexpr int encoding() const { assert(is_valid(), "invalid register"); return _encoding; } - inline VMReg as_VMReg() const; VectorSRegister successor() const { return VectorSRegister(encoding() + 1); } // testers @@ -484,8 +484,8 @@ class ConcreteRegisterImpl : public AbstractRegisterImpl { enum { max_gpr = Register::number_of_registers * 2, max_fpr = max_gpr + FloatRegister::number_of_registers * 2, - max_vsr = max_fpr + VectorSRegister::number_of_registers * 4, - max_cnd = max_vsr + ConditionRegister::number_of_registers, + max_vr = max_fpr + VectorRegister::number_of_registers * 4, + max_cnd = max_vr + ConditionRegister::number_of_registers, max_spr = max_cnd + SpecialRegister::number_of_registers, // This number must be large enough to cover REG_COUNT (defined by c2) registers. // There is no requirement that any ordering here matches any ordering c2 gives diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index 4ec2483b267..37d6c9e6d51 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -111,13 +111,13 @@ class RegisterSaver { int_reg, float_reg, special_reg, - vs_reg + vec_reg } RegisterType; typedef enum { reg_size = 8, half_reg_size = reg_size / 2, - vs_reg_size = 16 + vec_reg_size = 16 } RegisterConstants; typedef struct { @@ -137,8 +137,8 @@ class RegisterSaver { #define RegisterSaver_LiveSpecialReg(regname) \ { RegisterSaver::special_reg, regname->encoding(), regname->as_VMReg() } -#define RegisterSaver_LiveVSReg(regname) \ - { RegisterSaver::vs_reg, regname->encoding(), regname->as_VMReg() } +#define RegisterSaver_LiveVecReg(regname) \ + { RegisterSaver::vec_reg, regname->encoding(), regname->as_VMReg() } static const RegisterSaver::LiveRegType RegisterSaver_LiveRegs[] = { // Live registers which get spilled to the stack. Register @@ -220,42 +220,42 @@ static const RegisterSaver::LiveRegType RegisterSaver_LiveRegs[] = { RegisterSaver_LiveIntReg( R31 ) // must be the last register (see save/restore functions below) }; -static const RegisterSaver::LiveRegType RegisterSaver_LiveVSRegs[] = { +static const RegisterSaver::LiveRegType RegisterSaver_LiveVecRegs[] = { // - // live vector scalar registers (optional, only these ones are used by C2): + // live vector registers (optional, only these ones are used by C2): // - RegisterSaver_LiveVSReg( VSR32 ), - RegisterSaver_LiveVSReg( VSR33 ), - RegisterSaver_LiveVSReg( VSR34 ), - RegisterSaver_LiveVSReg( VSR35 ), - RegisterSaver_LiveVSReg( VSR36 ), - RegisterSaver_LiveVSReg( VSR37 ), - RegisterSaver_LiveVSReg( VSR38 ), - RegisterSaver_LiveVSReg( VSR39 ), - RegisterSaver_LiveVSReg( VSR40 ), - RegisterSaver_LiveVSReg( VSR41 ), - RegisterSaver_LiveVSReg( VSR42 ), - RegisterSaver_LiveVSReg( VSR43 ), - RegisterSaver_LiveVSReg( VSR44 ), - RegisterSaver_LiveVSReg( VSR45 ), - RegisterSaver_LiveVSReg( VSR46 ), - RegisterSaver_LiveVSReg( VSR47 ), - RegisterSaver_LiveVSReg( VSR48 ), - RegisterSaver_LiveVSReg( VSR49 ), - RegisterSaver_LiveVSReg( VSR50 ), - RegisterSaver_LiveVSReg( VSR51 ), - RegisterSaver_LiveVSReg( VSR52 ), - RegisterSaver_LiveVSReg( VSR53 ), - RegisterSaver_LiveVSReg( VSR54 ), - RegisterSaver_LiveVSReg( VSR55 ), - RegisterSaver_LiveVSReg( VSR56 ), - RegisterSaver_LiveVSReg( VSR57 ), - RegisterSaver_LiveVSReg( VSR58 ), - RegisterSaver_LiveVSReg( VSR59 ), - RegisterSaver_LiveVSReg( VSR60 ), - RegisterSaver_LiveVSReg( VSR61 ), - RegisterSaver_LiveVSReg( VSR62 ), - RegisterSaver_LiveVSReg( VSR63 ) + RegisterSaver_LiveVecReg( VR0 ), + RegisterSaver_LiveVecReg( VR1 ), + RegisterSaver_LiveVecReg( VR2 ), + RegisterSaver_LiveVecReg( VR3 ), + RegisterSaver_LiveVecReg( VR4 ), + RegisterSaver_LiveVecReg( VR5 ), + RegisterSaver_LiveVecReg( VR6 ), + RegisterSaver_LiveVecReg( VR7 ), + RegisterSaver_LiveVecReg( VR8 ), + RegisterSaver_LiveVecReg( VR9 ), + RegisterSaver_LiveVecReg( VR10 ), + RegisterSaver_LiveVecReg( VR11 ), + RegisterSaver_LiveVecReg( VR12 ), + RegisterSaver_LiveVecReg( VR13 ), + RegisterSaver_LiveVecReg( VR14 ), + RegisterSaver_LiveVecReg( VR15 ), + RegisterSaver_LiveVecReg( VR16 ), + RegisterSaver_LiveVecReg( VR17 ), + RegisterSaver_LiveVecReg( VR18 ), + RegisterSaver_LiveVecReg( VR19 ), + RegisterSaver_LiveVecReg( VR20 ), + RegisterSaver_LiveVecReg( VR21 ), + RegisterSaver_LiveVecReg( VR22 ), + RegisterSaver_LiveVecReg( VR23 ), + RegisterSaver_LiveVecReg( VR24 ), + RegisterSaver_LiveVecReg( VR25 ), + RegisterSaver_LiveVecReg( VR26 ), + RegisterSaver_LiveVecReg( VR27 ), + RegisterSaver_LiveVecReg( VR28 ), + RegisterSaver_LiveVecReg( VR29 ), + RegisterSaver_LiveVecReg( VR30 ), + RegisterSaver_LiveVecReg( VR31 ) }; @@ -277,10 +277,10 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble // calculate frame size const int regstosave_num = sizeof(RegisterSaver_LiveRegs) / sizeof(RegisterSaver::LiveRegType); - const int vsregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVSRegs) / + const int vecregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVecRegs) / sizeof(RegisterSaver::LiveRegType)) : 0; - const int register_save_size = regstosave_num * reg_size + vsregstosave_num * vs_reg_size; + const int register_save_size = regstosave_num * reg_size + vecregstosave_num * vec_reg_size; const int frame_size_in_bytes = align_up(register_save_size, frame::alignment_in_bytes) + frame::native_abi_reg_args_size; @@ -298,8 +298,8 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble // Save some registers in the last (non-vector) slots of the new frame so we // can use them as scratch regs or to determine the return pc. - __ std(R31, frame_size_in_bytes - reg_size - vsregstosave_num * vs_reg_size, R1_SP); - __ std(R30, frame_size_in_bytes - 2*reg_size - vsregstosave_num * vs_reg_size, R1_SP); + __ std(R31, frame_size_in_bytes - reg_size - vecregstosave_num * vec_reg_size, R1_SP); + __ std(R30, frame_size_in_bytes - 2*reg_size - vecregstosave_num * vec_reg_size, R1_SP); // save the flags // Do the save_LR by hand and adjust the return pc if requested. @@ -360,37 +360,37 @@ OopMap* RegisterSaver::push_frame_reg_args_and_save_live_registers(MacroAssemble // the utilized instructions (PowerArchitecturePPC64). assert(is_aligned(offset, StackAlignmentInBytes), "should be"); if (PowerArchitecturePPC64 >= 10) { - assert(is_even(vsregstosave_num), "expectation"); - for (int i = 0; i < vsregstosave_num; i += 2) { - int reg_num = RegisterSaver_LiveVSRegs[i].reg_num; - assert(RegisterSaver_LiveVSRegs[i + 1].reg_num == reg_num + 1, "or use other instructions!"); + assert(is_even(vecregstosave_num), "expectation"); + for (int i = 0; i < vecregstosave_num; i += 2) { + int reg_num = RegisterSaver_LiveVecRegs[i].reg_num; + assert(RegisterSaver_LiveVecRegs[i + 1].reg_num == reg_num + 1, "or use other instructions!"); - __ stxvp(as_VectorSRegister(reg_num), offset, R1_SP); + __ stxvp(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP); // Note: The contents were read in the same order (see loadV16_Power9 node in ppc.ad). if (generate_oop_map) { map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2), - RegisterSaver_LiveVSRegs[i LITTLE_ENDIAN_ONLY(+1) ].vmreg); - map->set_callee_saved(VMRegImpl::stack2reg((offset + vs_reg_size) >> 2), - RegisterSaver_LiveVSRegs[i BIG_ENDIAN_ONLY(+1) ].vmreg); + RegisterSaver_LiveVecRegs[i LITTLE_ENDIAN_ONLY(+1) ].vmreg); + map->set_callee_saved(VMRegImpl::stack2reg((offset + vec_reg_size) >> 2), + RegisterSaver_LiveVecRegs[i BIG_ENDIAN_ONLY(+1) ].vmreg); } - offset += (2 * vs_reg_size); + offset += (2 * vec_reg_size); } } else { - for (int i = 0; i < vsregstosave_num; i++) { - int reg_num = RegisterSaver_LiveVSRegs[i].reg_num; + for (int i = 0; i < vecregstosave_num; i++) { + int reg_num = RegisterSaver_LiveVecRegs[i].reg_num; if (PowerArchitecturePPC64 >= 9) { - __ stxv(as_VectorSRegister(reg_num), offset, R1_SP); + __ stxv(as_VectorRegister(reg_num)->to_vsr(), offset, R1_SP); } else { __ li(R31, offset); - __ stxvd2x(as_VectorSRegister(reg_num), R31, R1_SP); + __ stxvd2x(as_VectorRegister(reg_num)->to_vsr(), R31, R1_SP); } // Note: The contents were read in the same order (see loadV16_Power8 / loadV16_Power9 node in ppc.ad). if (generate_oop_map) { - VMReg vsr = RegisterSaver_LiveVSRegs[i].vmreg; + VMReg vsr = RegisterSaver_LiveVecRegs[i].vmreg; map->set_callee_saved(VMRegImpl::stack2reg(offset >> 2), vsr); } - offset += vs_reg_size; + offset += vec_reg_size; } } @@ -411,10 +411,10 @@ void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm, bool save_vectors) { const int regstosave_num = sizeof(RegisterSaver_LiveRegs) / sizeof(RegisterSaver::LiveRegType); - const int vsregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVSRegs) / + const int vecregstosave_num = save_vectors ? (sizeof(RegisterSaver_LiveVecRegs) / sizeof(RegisterSaver::LiveRegType)) : 0; - const int register_save_size = regstosave_num * reg_size + vsregstosave_num * vs_reg_size; + const int register_save_size = regstosave_num * reg_size + vecregstosave_num * vec_reg_size; const int register_save_offset = frame_size_in_bytes - register_save_size; @@ -456,26 +456,26 @@ void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm, assert(is_aligned(offset, StackAlignmentInBytes), "should be"); if (PowerArchitecturePPC64 >= 10) { - for (int i = 0; i < vsregstosave_num; i += 2) { - int reg_num = RegisterSaver_LiveVSRegs[i].reg_num; - assert(RegisterSaver_LiveVSRegs[i + 1].reg_num == reg_num + 1, "or use other instructions!"); + for (int i = 0; i < vecregstosave_num; i += 2) { + int reg_num = RegisterSaver_LiveVecRegs[i].reg_num; + assert(RegisterSaver_LiveVecRegs[i + 1].reg_num == reg_num + 1, "or use other instructions!"); - __ lxvp(as_VectorSRegister(reg_num), offset, R1_SP); + __ lxvp(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP); - offset += (2 * vs_reg_size); + offset += (2 * vec_reg_size); } } else { - for (int i = 0; i < vsregstosave_num; i++) { - int reg_num = RegisterSaver_LiveVSRegs[i].reg_num; + for (int i = 0; i < vecregstosave_num; i++) { + int reg_num = RegisterSaver_LiveVecRegs[i].reg_num; if (PowerArchitecturePPC64 >= 9) { - __ lxv(as_VectorSRegister(reg_num), offset, R1_SP); + __ lxv(as_VectorRegister(reg_num).to_vsr(), offset, R1_SP); } else { __ li(R31, offset); - __ lxvd2x(as_VectorSRegister(reg_num), R31, R1_SP); + __ lxvd2x(as_VectorRegister(reg_num).to_vsr(), R31, R1_SP); } - offset += vs_reg_size; + offset += vec_reg_size; } } @@ -486,7 +486,7 @@ void RegisterSaver::restore_live_registers_and_pop_frame(MacroAssembler* masm, __ mtlr(R31); // restore scratch register's value - __ ld(R31, frame_size_in_bytes - reg_size - vsregstosave_num * vs_reg_size, R1_SP); + __ ld(R31, frame_size_in_bytes - reg_size - vecregstosave_num * vec_reg_size, R1_SP); // pop the frame __ addi(R1_SP, R1_SP, frame_size_in_bytes); diff --git a/src/hotspot/cpu/ppc/vmreg_ppc.cpp b/src/hotspot/cpu/ppc/vmreg_ppc.cpp index 2ed68578a80..0edbf700ec6 100644 --- a/src/hotspot/cpu/ppc/vmreg_ppc.cpp +++ b/src/hotspot/cpu/ppc/vmreg_ppc.cpp @@ -47,7 +47,7 @@ void VMRegImpl::set_regName() { } VectorSRegister vsreg = ::as_VectorSRegister(0); - for ( ; i < ConcreteRegisterImpl::max_vsr; ) { + for ( ; i < ConcreteRegisterImpl::max_vr; ) { regName[i++] = vsreg->name(); regName[i++] = vsreg->name(); regName[i++] = vsreg->name(); diff --git a/src/hotspot/cpu/ppc/vmreg_ppc.hpp b/src/hotspot/cpu/ppc/vmreg_ppc.hpp index 4e25c8b3cea..194b5fd93ef 100644 --- a/src/hotspot/cpu/ppc/vmreg_ppc.hpp +++ b/src/hotspot/cpu/ppc/vmreg_ppc.hpp @@ -35,13 +35,13 @@ inline bool is_FloatRegister() { value() < ConcreteRegisterImpl::max_fpr; } -inline bool is_VectorSRegister() { +inline bool is_VectorRegister() { return value() >= ConcreteRegisterImpl::max_fpr && - value() < ConcreteRegisterImpl::max_vsr; + value() < ConcreteRegisterImpl::max_vr; } inline bool is_ConditionRegister() { - return value() >= ConcreteRegisterImpl::max_vsr && + return value() >= ConcreteRegisterImpl::max_vr && value() < ConcreteRegisterImpl::max_cnd; } @@ -60,15 +60,15 @@ inline FloatRegister as_FloatRegister() { return ::as_FloatRegister((value() - ConcreteRegisterImpl::max_gpr) >> 1); } -inline VectorSRegister as_VectorSRegister() { - assert(is_VectorSRegister(), "must be"); - return ::as_VectorSRegister((value() - ConcreteRegisterImpl::max_fpr) >> 2); +inline VectorRegister as_VectorRegister() { + assert(is_VectorRegister(), "must be"); + return ::as_VectorRegister((value() - ConcreteRegisterImpl::max_fpr) >> 2); } inline bool is_concrete() { assert(is_reg(), "must be"); if (is_Register() || is_FloatRegister()) return is_even(value()); - if (is_VectorSRegister()) { + if (is_VectorRegister()) { int base = value() - ConcreteRegisterImpl::max_fpr; return (base & 3) == 0; } diff --git a/src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp b/src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp index 2424df8da01..a7810266b89 100644 --- a/src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/vmreg_ppc.inline.hpp @@ -40,13 +40,13 @@ inline VMReg FloatRegister::as_VMReg() const { return VMRegImpl::as_VMReg((encoding() << 1) + ConcreteRegisterImpl::max_gpr); } -inline VMReg VectorSRegister::as_VMReg() const { +inline VMReg VectorRegister::as_VMReg() const { // Four halves, multiply by 4. return VMRegImpl::as_VMReg((encoding() << 2) + ConcreteRegisterImpl::max_fpr); } inline VMReg ConditionRegister::as_VMReg() const { - return VMRegImpl::as_VMReg((encoding()) + ConcreteRegisterImpl::max_vsr); + return VMRegImpl::as_VMReg((encoding()) + ConcreteRegisterImpl::max_vr); } inline VMReg SpecialRegister::as_VMReg() const { From f62f1178aa01d812ee8ffb1d3dd165b4cf157186 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 17 Jun 2025 12:32:17 +0000 Subject: [PATCH 081/213] 8359701: G1: Move heap expansion time tracking of G1CollectedHeap:expand to call site Reviewed-by: tschatzl, iwalulya --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 15 +++++---------- src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 2 +- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index c83414eac82..b6c18420b82 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1001,7 +1001,7 @@ HeapWord* G1CollectedHeap::expand_and_allocate(size_t word_size) { return nullptr; } -bool G1CollectedHeap::expand(size_t expand_bytes, WorkerThreads* pretouch_workers, double* expand_time_ms) { +bool G1CollectedHeap::expand(size_t expand_bytes, WorkerThreads* pretouch_workers) { size_t aligned_expand_bytes = os::align_up_vm_page_size(expand_bytes); aligned_expand_bytes = align_up(aligned_expand_bytes, G1HeapRegion::GrainBytes); @@ -1013,15 +1013,10 @@ bool G1CollectedHeap::expand(size_t expand_bytes, WorkerThreads* pretouch_worker return false; } - double expand_heap_start_time_sec = os::elapsedTime(); uint regions_to_expand = (uint)(aligned_expand_bytes / G1HeapRegion::GrainBytes); assert(regions_to_expand > 0, "Must expand by at least one region"); uint expanded_by = _hrm.expand_by(regions_to_expand, pretouch_workers); - if (expand_time_ms != nullptr) { - *expand_time_ms = (os::elapsedTime() - expand_heap_start_time_sec) * MILLIUNITS; - } - assert(expanded_by > 0, "must have failed during commit."); size_t actual_expand_bytes = expanded_by * G1HeapRegion::GrainBytes; @@ -2397,11 +2392,11 @@ void G1CollectedHeap::expand_heap_after_young_collection(){ if (expand_bytes > 0) { // No need for an ergo logging here, // expansion_amount() does this when it returns a value > 0. - double expand_ms = 0.0; - if (!expand(expand_bytes, _workers, &expand_ms)) { - // We failed to expand the heap. Cannot do anything about it. + Ticks expand_start = Ticks::now(); + if (expand(expand_bytes, _workers)) { + double expand_ms = (Ticks::now() - expand_start).seconds() * MILLIUNITS; + phase_times()->record_expand_heap_time(expand_ms); } - phase_times()->record_expand_heap_time(expand_ms); } } diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 838e3b000e0..ad440577f2d 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -572,7 +572,7 @@ class G1CollectedHeap : public CollectedHeap { // Returns true if the heap was expanded by the requested amount; // false otherwise. // (Rounds up to a G1HeapRegion boundary.) - bool expand(size_t expand_bytes, WorkerThreads* pretouch_workers, double* expand_time_ms = nullptr); + bool expand(size_t expand_bytes, WorkerThreads* pretouch_workers); bool expand_single_region(uint node_index); // Returns the PLAB statistics for a given destination. From c1deb9eebf1adecffe5b205486477009ec2f7348 Mon Sep 17 00:00:00 2001 From: Anton Artemov Date: Tue, 17 Jun 2025 13:46:13 +0000 Subject: [PATCH 082/213] 8356556: AArch64: No need for acquire fence in safepoint poll in FFM Reviewed-by: dholmes, pchilanomate --- src/hotspot/cpu/aarch64/aarch64.ad | 2 +- src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp | 2 +- src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp | 9 ++------- src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp | 2 +- src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp | 2 +- .../cpu/aarch64/templateInterpreterGenerator_aarch64.cpp | 8 ++++---- 8 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 75baef153f8..58567e9f713 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1888,7 +1888,7 @@ void MachEpilogNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); - __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); + __ safepoint_poll(*code_stub, true /* at_return */, true /* in_nmethod */); } } diff --git a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp index 9730e75f266..9e96002187f 100644 --- a/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_LIRAssembler_aarch64.cpp @@ -483,7 +483,7 @@ void LIR_Assembler::return_op(LIR_Opr result, C1SafepointPollStub* code_stub) { code_stub->set_safepoint_offset(__ offset()); __ relocate(relocInfo::poll_return_type); - __ safepoint_poll(*code_stub->entry(), true /* at_return */, false /* acquire */, true /* in_nmethod */); + __ safepoint_poll(*code_stub->entry(), true /* at_return */, true /* in_nmethod */); __ ret(lr); } diff --git a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp index f30b5d7cf2c..65d448f908c 100644 --- a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp @@ -289,7 +289,7 @@ void DowncallLinker::StubGenerator::generate() { __ verify_sve_vector_length(tmp1); - __ safepoint_poll(L_safepoint_poll_slow_path, true /* at_return */, true /* acquire */, false /* in_nmethod */, tmp1); + __ safepoint_poll(L_safepoint_poll_slow_path, true /* at_return */, false /* in_nmethod */, tmp1); __ ldrw(tmp1, Address(rthread, JavaThread::suspend_flags_offset())); __ cbnzw(tmp1, L_safepoint_poll_slow_path); diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index 276fdd013db..35d6ebfae4b 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -603,7 +603,7 @@ void InterpreterMacroAssembler::remove_activation(TosState state, // the stack, will call InterpreterRuntime::at_unwind. Label slow_path; Label fast_path; - safepoint_poll(slow_path, true /* at_return */, false /* acquire */, false /* in_nmethod */); + safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); br(Assembler::AL, fast_path); bind(slow_path); push(state); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index a277a689280..93b303e51c9 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -553,13 +553,8 @@ address MacroAssembler::target_addr_for_insn_or_null(address insn_addr, unsigned return MacroAssembler::target_addr_for_insn(insn_addr, insn); } -void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod, Register tmp) { - if (acquire) { - lea(tmp, Address(rthread, JavaThread::polling_word_offset())); - ldar(tmp, tmp); - } else { - ldr(tmp, Address(rthread, JavaThread::polling_word_offset())); - } +void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod, Register tmp) { + ldr(tmp, Address(rthread, JavaThread::polling_word_offset())); if (at_return) { // Note that when in_nmethod is set, the stack pointer is incremented before the poll. Therefore, // we may safely use the sp instead to perform the stack watermark check. diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index f5f0f630c0c..fe2440fd3fd 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -120,7 +120,7 @@ class MacroAssembler: public Assembler { virtual void check_and_handle_popframe(Register java_thread); virtual void check_and_handle_earlyret(Register java_thread); - void safepoint_poll(Label& slow_path, bool at_return, bool acquire, bool in_nmethod, Register tmp = rscratch1); + void safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod, Register tmp = rscratch1); void rt_call(address dest, Register tmp = rscratch1); // Load Effective Address diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 51f18cb1bbe..da2f939e7af 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -1877,7 +1877,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm, // Check for safepoint operation in progress and/or pending suspend requests. { // No need for acquire as Java threads always disarm themselves. - __ safepoint_poll(safepoint_in_progress, true /* at_return */, false /* acquire */, false /* in_nmethod */); + __ safepoint_poll(safepoint_in_progress, true /* at_return */, 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 710970d1ea2..6593406902f 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -1018,7 +1018,7 @@ address TemplateInterpreterGenerator::generate_CRC32_update_entry() { Label slow_path; // If we need a safepoint check, generate full interpreter entry. - __ safepoint_poll(slow_path, false /* at_return */, false /* acquire */, false /* in_nmethod */); + __ safepoint_poll(slow_path, false /* at_return */, false /* in_nmethod */); // We don't generate local frame and don't align stack because // we call stub code and there is no safepoint on this path. @@ -1065,7 +1065,7 @@ address TemplateInterpreterGenerator::generate_CRC32_updateBytes_entry(AbstractI Label slow_path; // If we need a safepoint check, generate full interpreter entry. - __ safepoint_poll(slow_path, false /* at_return */, false /* acquire */, false /* in_nmethod */); + __ safepoint_poll(slow_path, false /* at_return */, false /* in_nmethod */); // We don't generate local frame and don't align stack because // we call stub code and there is no safepoint on this path. @@ -1455,7 +1455,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { Label L, Continue; // No need for acquire as Java threads always disarm themselves. - __ safepoint_poll(L, true /* at_return */, false /* acquire */, false /* in_nmethod */); + __ safepoint_poll(L, true /* at_return */, false /* in_nmethod */); __ ldrw(rscratch2, Address(rthread, JavaThread::suspend_flags_offset())); __ cbz(rscratch2, Continue); __ bind(L); @@ -1608,7 +1608,7 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { Label slow_path; Label fast_path; - __ safepoint_poll(slow_path, true /* at_return */, false /* acquire */, false /* in_nmethod */); + __ safepoint_poll(slow_path, true /* at_return */, false /* in_nmethod */); __ br(Assembler::AL, fast_path); __ bind(slow_path); __ push(dtos); From 51877f568ba84a8ec7721656571c90c5eb952eb3 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Tue, 17 Jun 2025 13:50:01 +0000 Subject: [PATCH 083/213] 8359207: Remove runtime/signal/TestSigusr2.java since it is always skipped Reviewed-by: dcubed, dholmes --- .../jtreg/runtime/signal/SigTestDriver.java | 10 ++---- .../jtreg/runtime/signal/TestSigusr2.java | 35 ------------------- 2 files changed, 2 insertions(+), 43 deletions(-) delete mode 100644 test/hotspot/jtreg/runtime/signal/TestSigusr2.java diff --git a/test/hotspot/jtreg/runtime/signal/SigTestDriver.java b/test/hotspot/jtreg/runtime/signal/SigTestDriver.java index 4a62a1e9cca..9a139baf68d 100644 --- a/test/hotspot/jtreg/runtime/signal/SigTestDriver.java +++ b/test/hotspot/jtreg/runtime/signal/SigTestDriver.java @@ -53,15 +53,9 @@ public static void main(String[] args) { switch (signame) { case "SIGWAITING": case "SIGKILL": - case "SIGSTOP": { - throw new SkippedException("signals SIGWAITING, SIGKILL and SIGSTOP can't be tested"); - } + case "SIGSTOP": case "SIGUSR2": { - if (Platform.isLinux()) { - throw new SkippedException("SIGUSR2 can't be tested on Linux"); - } else if (Platform.isOSX()) { - throw new SkippedException("SIGUSR2 can't be tested on OS X"); - } + throw new SkippedException("signals SIGWAITING, SIGKILL, SIGSTOP and SIGUSR2 can't be tested"); } } diff --git a/test/hotspot/jtreg/runtime/signal/TestSigusr2.java b/test/hotspot/jtreg/runtime/signal/TestSigusr2.java deleted file mode 100644 index fc5bff9d67d..00000000000 --- a/test/hotspot/jtreg/runtime/signal/TestSigusr2.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - - -/* - * @test - * @requires os.family != "windows" & os.family != "aix" - * - * @summary converted from VM testbase runtime/signal/sigusr201. - * VM testbase keywords: [signal, runtime, linux, macosx] - * - * @library /test/lib - * @run main/native SigTestDriver SIGUSR2 - */ - From 21b72dea7805357b3644161d1a158c52f49d0e6e Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Tue, 17 Jun 2025 14:01:06 +0000 Subject: [PATCH 084/213] 8357862: Java argument file is parsed unexpectedly with trailing comment Co-authored-by: Stuart Marks Reviewed-by: vromero --- src/java.base/share/native/libjli/args.c | 29 ++++++++++++++++------ test/jdk/tools/launcher/ArgFileSyntax.java | 15 ++++++++--- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/java.base/share/native/libjli/args.c b/src/java.base/share/native/libjli/args.c index 547b279b7de..2f8fdf0fc43 100644 --- a/src/java.base/share/native/libjli/args.c +++ b/src/java.base/share/native/libjli/args.c @@ -149,6 +149,19 @@ static void checkArg(const char *arg) { } } +static char *computeToken(JLI_List *parts, const char *anchor, const char *nextc) { + char *token; + if ((*parts)->size == 0) { + token = clone_substring(anchor, nextc - anchor); + } else { + JLI_List_addSubstring(*parts, anchor, nextc - anchor); + token = JLI_List_combine(*parts); + JLI_List_free(*parts); + *parts = JLI_List_new(4); + } + return token; +} + /* [\n\r] +------------+ +------------+ [\n\r] +---------+ IN_COMMENT +<------+ | IN_ESCAPE +---------+ @@ -246,14 +259,7 @@ static char* nextToken(__ctx_args *pctx) { // fall through case '\n': case '\r': - if (pctx->parts->size == 0) { - token = clone_substring(anchor, nextc - anchor); - } else { - JLI_List_addSubstring(pctx->parts, anchor, nextc - anchor); - token = JLI_List_combine(pctx->parts); - JLI_List_free(pctx->parts); - pctx->parts = JLI_List_new(4); - } + token = computeToken(&pctx->parts, anchor, nextc); pctx->cptr = nextc + 1; pctx->state = FIND_NEXT; return token; @@ -262,6 +268,13 @@ static char* nextToken(__ctx_args *pctx) { continue; } pctx->state = IN_COMMENT; + // return non-zero length token, terminated by the number sign + if (nextc - anchor > 0) { + token = computeToken(&pctx->parts, anchor, nextc); + pctx->cptr = nextc + 1; + return token; + } + // anchor after number sign anchor = nextc + 1; break; case '\\': diff --git a/test/jdk/tools/launcher/ArgFileSyntax.java b/test/jdk/tools/launcher/ArgFileSyntax.java index bedb0d36fc5..5145c205166 100644 --- a/test/jdk/tools/launcher/ArgFileSyntax.java +++ b/test/jdk/tools/launcher/ArgFileSyntax.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,9 +21,9 @@ * questions. */ -/** +/* * @test - * @bug 8027634 8210810 8240629 + * @bug 8027634 8210810 8240629 8357862 * @summary Verify syntax of argument file * @build TestHelper * @run main ArgFileSyntax @@ -172,6 +172,15 @@ private void verifyOutput(List args, TestResult tr) { "-version", "-Dcontinue.with.leadingws=Line1continue with \f and \t" } + }, + { // multiple args in one line and comments without preceding whitespace + { "-Xmx32m -XshowSettings#COMMENT 1", + "-version#COMMENT 2" + }, + { "-Xmx32m", + "-XshowSettings", + "-version" + } } }; From 53a83d15a1b5686ed0f2aeb3d30cd46b73f80733 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Tue, 17 Jun 2025 14:09:11 +0000 Subject: [PATCH 085/213] 8357799: Improve instructions for JFileChooser/HTMLFileName.java Reviewed-by: honkar, tr, kizune --- .../swing/JFileChooser/HTMLFileName.java | 67 +++++++++++-------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/test/jdk/javax/swing/JFileChooser/HTMLFileName.java b/test/jdk/javax/swing/JFileChooser/HTMLFileName.java index 45d9cb4c449..a8bc9525cca 100644 --- a/test/jdk/javax/swing/JFileChooser/HTMLFileName.java +++ b/test/jdk/javax/swing/JFileChooser/HTMLFileName.java @@ -52,24 +52,35 @@ public class HTMLFileName { private static final String INSTRUCTIONS = """
      -
    1. FileChooser shows up a virtual directory and file with name -

      Swing Rocks!. -
    2. On "HTML disabled" frame : +
    3. JFileChooser shows a virtual directory. + The first file in the list has the following name: + <html><h1 color=#ff00ff><font + face="Serif">Swing Rocks! +
      +
      +
    4. In HTML disabled frame:
        -
      1. Verify that the folder and file name must be plain text. -
      2. If the name in file pane window and also in directory - ComboBox remains in plain text, then press Pass. - If it appears to be in HTML format with Pink color as - shown, then press Fail. +
      3. Verify that the first file name displays + as plain text, + that is you see the HTML tags in the file name. +
      4. If the file name in the file pane and + in the navigation combo box above is displayed + as HTML, that is in large font and magenta color, + then press Fail.
      -
    5. On "HTML enabled" frame : +
    6. In HTML enabled frame:
        -
      1. Verify that the folder and file name remains in HTML - format with name "Swing Rocks!" pink in color as shown. -
      2. If the name in file pane window and also in directory - ComboBox remains in HTML format string, then press Pass. - If it appears to be in plain text, then press Fail. +
      3. Verify that the first file name displays as HTML, + that is Swing Rocks! in large font + and magenta color.
        + Note: On macOS in Aqua L&F, the file name with + HTML displays as an empty file name. It is not an error. +
      4. If the file name in the file pane and + in the navigation combo box above is displayed + as HTML, then press Pass.
        + If it is in plain text, then press Fail.
    @@ -99,6 +110,7 @@ public static void main(String[] args) throws Exception { PassFailJFrame.builder() .instructions(INSTRUCTIONS) .columns(45) + .rows(20) .testUI(HTMLFileName::initialize) .positionTestUIBottomRowCentered() .build() @@ -110,18 +122,25 @@ private static List initialize() { return List.of(createFileChooser(true), createFileChooser(false)); } - private static JFrame createFileChooser(boolean htmlEnabled) { + private static JFrame createFileChooser(boolean htmlDisabled) { JFileChooser jfc = new JFileChooser(new VirtualFileSystemView()); - jfc.putClientProperty("html.disable", htmlEnabled); + jfc.putClientProperty("html.disable", htmlDisabled); jfc.setControlButtonsAreShown(false); - JFrame frame = new JFrame((htmlEnabled) ? "HTML enabled" : "HTML disabled"); + JFrame frame = new JFrame(htmlDisabled ? "HTML disabled" : "HTML enabled"); frame.add(jfc); frame.pack(); return frame; } private static class VirtualFileSystemView extends FileSystemView { + private final File[] files = { + new File("/", "

    Swing Rocks!"), + new File("/", "virtualFile1.txt"), + new File("/", "virtualFile2.log") + }; + @Override public File createNewFolder(File containingDir) { return null; @@ -129,12 +148,7 @@ public File createNewFolder(File containingDir) { @Override public File[] getRoots() { - return new File[]{ - new File("/", "

    Swing Rocks!"), - new File("/", "virtualFile2.txt"), - new File("/", "virtualFolder") - }; + return files; } @Override @@ -150,12 +164,7 @@ public File getDefaultDirectory() { @Override public File[] getFiles(File dir, boolean useFileHiding) { // Simulate a virtual folder structure - return new File[]{ - new File("/", "

    Swing Rocks!"), - new File(dir, "virtualFile2.txt"), - new File(dir, "virtualFolder") - }; + return files; } @Override From 96070212adfd15acd99edf6e180db6228ee7b4ff Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Tue, 17 Jun 2025 15:55:14 +0000 Subject: [PATCH 086/213] 8359646: C1 crash in AOTCodeAddressTable::add_C_string Reviewed-by: adinn, iklam --- src/hotspot/share/code/aotCodeCache.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp index cb318938819..da0be2403fa 100644 --- a/src/hotspot/share/code/aotCodeCache.cpp +++ b/src/hotspot/share/code/aotCodeCache.cpp @@ -389,6 +389,7 @@ AOTCodeCache::~AOTCodeCache() { _store_buffer = nullptr; } if (_table != nullptr) { + MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag); delete _table; _table = nullptr; } @@ -819,6 +820,9 @@ bool AOTCodeCache::store_code_blob(CodeBlob& blob, AOTCodeEntry::Kind entry_kind // we need to take a lock to prevent race between compiler threads generating AOT code // and the main thread generating adapter MutexLocker ml(Compile_lock); + if (!is_on()) { + return false; // AOT code cache was already dumped and closed. + } if (!cache->align_write()) { return false; } @@ -1530,6 +1534,7 @@ void AOTCodeCache::load_strings() { int AOTCodeCache::store_strings() { if (_C_strings_used > 0) { + MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag); uint offset = _write_position; uint length = 0; uint* lengths = (uint *)reserve_bytes(sizeof(uint) * _C_strings_used); @@ -1555,15 +1560,17 @@ int AOTCodeCache::store_strings() { const char* AOTCodeCache::add_C_string(const char* str) { if (is_on_for_dump() && str != nullptr) { - return _cache->_table->add_C_string(str); + MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag); + AOTCodeAddressTable* table = addr_table(); + if (table != nullptr) { + return table->add_C_string(str); + } } return str; } const char* AOTCodeAddressTable::add_C_string(const char* str) { if (_extrs_complete) { - LogStreamHandle(Trace, aot, codecache, stringtable) log; // ctor outside lock - MutexLocker ml(AOTCodeCStrings_lock, Mutex::_no_safepoint_check_flag); // Check previous strings address for (int i = 0; i < _C_strings_count; i++) { if (_C_strings_in[i] == str) { @@ -1580,9 +1587,7 @@ const char* AOTCodeAddressTable::add_C_string(const char* str) { _C_strings_in[_C_strings_count] = str; const char* dup = os::strdup(str); _C_strings[_C_strings_count++] = dup; - if (log.is_enabled()) { - log.print_cr("add_C_string: [%d] " INTPTR_FORMAT " '%s'", _C_strings_count, p2i(dup), dup); - } + log_trace(aot, codecache, stringtable)("add_C_string: [%d] " INTPTR_FORMAT " '%s'", _C_strings_count, p2i(dup), dup); return dup; } else { assert(false, "Number of C strings >= MAX_STR_COUNT"); From 49a82d880636a632f4a3471b14b1b1b29ce1d5e6 Mon Sep 17 00:00:00 2001 From: dermster Date: Tue, 17 Jun 2025 18:21:40 +0000 Subject: [PATCH 087/213] 8359449: [TEST] open/test/jdk/java/io/File/SymLinks.java Refactor extract method for Windows specific test Reviewed-by: bpb --- test/jdk/java/io/File/SymLinks.java | 39 ++++++++++++++++------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/test/jdk/java/io/File/SymLinks.java b/test/jdk/java/io/File/SymLinks.java index 967250c8430..40205a41557 100644 --- a/test/jdk/java/io/File/SymLinks.java +++ b/test/jdk/java/io/File/SymLinks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -281,22 +281,7 @@ static void go() throws IOException { assertTrue(link2dir.isDirectory()); assertTrue(link2link2dir.isDirectory()); - // on Windows we test with the DOS hidden attribute set - if (System.getProperty("os.name").startsWith("Windows")) { - DosFileAttributeView view = Files - .getFileAttributeView(file.toPath(), DosFileAttributeView.class); - view.setHidden(true); - try { - assertTrue(file.isHidden()); - assertTrue(link2file.isHidden()); - assertTrue(link2link2file.isHidden()); - } finally { - view.setHidden(false); - } - assertFalse(file.isHidden()); - assertFalse(link2file.isHidden()); - assertFalse(link2link2file.isHidden()); - } + testDOSHiddenAttributes(); header("length"); @@ -362,6 +347,26 @@ static void go() throws IOException { } } + static void testDOSHiddenAttributes() throws IOException { + // on Windows we test with the DOS hidden attribute set + if (System.getProperty("os.name").startsWith("Windows")) { + header("testDOSHiddenAttributes"); + DosFileAttributeView view = Files + .getFileAttributeView(file.toPath(), DosFileAttributeView.class); + view.setHidden(true); + try { + assertTrue(file.isHidden()); + assertTrue(link2file.isHidden()); + assertTrue(link2link2file.isHidden()); + } finally { + view.setHidden(false); + } + assertFalse(file.isHidden()); + assertFalse(link2file.isHidden()); + assertFalse(link2link2file.isHidden()); + } + } + public static void main(String[] args) throws IOException { if (supportsSymLinks(top)) { try { From 164cae469ca0b97b01ce36402a248be308419af6 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Tue, 17 Jun 2025 19:22:14 +0000 Subject: [PATCH 088/213] 8359733: UnProblemList serviceability/jvmti/vthread/SuspendWithInterruptLock Reviewed-by: syan, dholmes, lmesnik --- test/hotspot/jtreg/ProblemList-Xcomp.txt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt index 6df68c1ed62..b30ab329495 100644 --- a/test/hotspot/jtreg/ProblemList-Xcomp.txt +++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -35,8 +35,6 @@ vmTestbase/vm/mlvm/mixed/stress/regression/b6969574/INDIFY_Test.java 8265295 lin serviceability/AsyncGetCallTrace/MyPackage/ASGCTBaseTest.java 8303168 linux-all -serviceability/jvmti/vthread/SuspendWithInterruptLock/SuspendWithInterruptLock.java#default 8312064 generic-all - serviceability/sa/ClhsdbInspect.java 8283578 windows-x64 vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_a/TestDescription.java 8308367 generic-all From afa52e4681f5d0392c3fdfddf48b00a004d1280c Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Tue, 17 Jun 2025 20:23:20 +0000 Subject: [PATCH 089/213] 8210549: Runtime.exec: in closeDescriptors(), use FD_CLOEXEC instead of close() Reviewed-by: rriggs --- make/test/JtregNativeJdk.gmk | 2 +- src/java.base/unix/native/libjava/childproc.c | 54 ++++++++------ .../ProcessBuilder/FDLeakTest/FDLeakTest.java | 72 +++++++++++++++++++ .../FDLeakTest/exeFDLeakTester.c | 56 +++++++++++++++ .../ProcessBuilder/FDLeakTest/libFDLeaker.c | 36 ++++++++++ 5 files changed, 197 insertions(+), 23 deletions(-) create mode 100644 test/jdk/java/lang/ProcessBuilder/FDLeakTest/FDLeakTest.java create mode 100644 test/jdk/java/lang/ProcessBuilder/FDLeakTest/exeFDLeakTester.c create mode 100644 test/jdk/java/lang/ProcessBuilder/FDLeakTest/libFDLeaker.c diff --git a/make/test/JtregNativeJdk.gmk b/make/test/JtregNativeJdk.gmk index 60a88ca1c9a..f5970527648 100644 --- a/make/test/JtregNativeJdk.gmk +++ b/make/test/JtregNativeJdk.gmk @@ -62,7 +62,7 @@ BUILD_JDK_JTREG_LIBRARIES_JDK_LIBS_libGetXSpace := java.base:libjava ifeq ($(call isTargetOs, windows), true) BUILD_JDK_JTREG_EXCLUDE += libDirectIO.c libInheritedChannel.c \ libExplicitAttach.c libImplicitAttach.c \ - exelauncher.c + exelauncher.c libFDLeaker.c exeFDLeakTester.c BUILD_JDK_JTREG_EXECUTABLES_LIBS_exeNullCallerTest := $(LIBCXX) BUILD_JDK_JTREG_EXECUTABLES_LIBS_exerevokeall := advapi32.lib diff --git a/src/java.base/unix/native/libjava/childproc.c b/src/java.base/unix/native/libjava/childproc.c index 7a21b86565f..0dc0788879e 100644 --- a/src/java.base/unix/native/libjava/childproc.c +++ b/src/java.base/unix/native/libjava/childproc.c @@ -52,6 +52,21 @@ closeSafely(int fd) return (fd == -1) ? 0 : close(fd); } +int +markCloseOnExec(int fd) +{ + const int flags = fcntl(fd, F_GETFD); + if (flags < 0) { + return -1; + } + if ((flags & FD_CLOEXEC) == 0) { + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { + return -1; + } + } + return 0; +} + static int isAsciiDigit(char c) { @@ -68,21 +83,15 @@ isAsciiDigit(char c) #endif static int -closeDescriptors(void) +markDescriptorsCloseOnExec(void) { DIR *dp; struct dirent *dirp; - int from_fd = FAIL_FILENO + 1; - - /* We're trying to close all file descriptors, but opendir() might - * itself be implemented using a file descriptor, and we certainly - * don't want to close that while it's in use. We assume that if - * opendir() is implemented using a file descriptor, then it uses - * the lowest numbered file descriptor, just like open(). So we - * close a couple explicitly. */ - - close(from_fd); /* for possible use by opendir() */ - close(from_fd + 1); /* another one for good luck */ + /* This function marks all file descriptors beyond stderr as CLOEXEC. + * That includes the file descriptor used for the fail pipe: we want that + * one to stay open up until the execve, but it should be closed with the + * execve. */ + const int fd_from = STDERR_FILENO + 1; #if defined(_AIX) /* AIX does not understand '/proc/self' - it requires the real process ID */ @@ -91,18 +100,22 @@ closeDescriptors(void) #endif if ((dp = opendir(FD_DIR)) == NULL) - return 0; + return -1; while ((dirp = readdir(dp)) != NULL) { int fd; if (isAsciiDigit(dirp->d_name[0]) && - (fd = strtol(dirp->d_name, NULL, 10)) >= from_fd + 2) - close(fd); + (fd = strtol(dirp->d_name, NULL, 10)) >= fd_from) { + if (markCloseOnExec(fd) == -1) { + closedir(dp); + return -1; + } + } } closedir(dp); - return 1; + return 0; } static int @@ -394,11 +407,11 @@ childProcess(void *arg) fail_pipe_fd = FAIL_FILENO; /* close everything */ - if (closeDescriptors() == 0) { /* failed, close the old way */ + if (markDescriptorsCloseOnExec() == -1) { /* failed, close the old way */ int max_fd = (int)sysconf(_SC_OPEN_MAX); int fd; - for (fd = FAIL_FILENO + 1; fd < max_fd; fd++) - if (close(fd) == -1 && errno != EBADF) + for (fd = STDERR_FILENO + 1; fd < max_fd; fd++) + if (markCloseOnExec(fd) == -1 && errno != EBADF) goto WhyCantJohnnyExec; } @@ -413,9 +426,6 @@ childProcess(void *arg) sigprocmask(SIG_SETMASK, &unblock_signals, NULL); } - if (fcntl(FAIL_FILENO, F_SETFD, FD_CLOEXEC) == -1) - goto WhyCantJohnnyExec; - JDK_execvpe(p->mode, p->argv[0], p->argv, p->envv); WhyCantJohnnyExec: diff --git a/test/jdk/java/lang/ProcessBuilder/FDLeakTest/FDLeakTest.java b/test/jdk/java/lang/ProcessBuilder/FDLeakTest/FDLeakTest.java new file mode 100644 index 00000000000..146c2be563f --- /dev/null +++ b/test/jdk/java/lang/ProcessBuilder/FDLeakTest/FDLeakTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/** + * @test id=posix_spawn + * @summary Check that we don't leak FDs + * @requires os.family != "windows" + * @library /test/lib + * @run main/othervm/native -Djdk.lang.Process.launchMechanism=posix_spawn -agentlib:FDLeaker FDLeakTest + */ + +/** + * @test id=fork + * @summary Check that we don't leak FDs + * @requires os.family != "windows" + * @library /test/lib + * @run main/othervm/native -Djdk.lang.Process.launchMechanism=fork -agentlib:FDLeaker FDLeakTest + */ + +/** + * @test id=vfork + * @summary Check that we don't leak FDs + * @requires os.family == "linux" + * @library /test/lib + * @run main/othervm/native -Djdk.lang.Process.launchMechanism=vfork -agentlib:FDLeaker FDLeakTest + */ + +import jdk.test.lib.process.ProcessTools; +public class FDLeakTest { + // This test has two native parts: + // - a library invoked with -agentlib that ensures that, in the parent JVM, we open + // a native fd without setting FD_CLOEXEC (libFDLeaker.c). This is necessary because + // there is no way to do this from Java: if Java functions correctly, all files the + // user could open via its APIs should be marked with FD_CLOEXEC. + // - a small native executable that tests - without using /proc - whether any file + // descriptors other than stdin/out/err are open. + // + // What should happen: In the child process, between the initial fork and the exec of + // the target binary, we should close all filedescriptors that are not stdin/out/err. + // If that works, the child process should not see any other file descriptors save + // those three. + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createNativeTestProcessBuilder("FDLeakTester"); + pb.inheritIO(); + Process p = pb.start(); + p.waitFor(); + if (p.exitValue() != 0) { + throw new RuntimeException("Failed"); + } + } +} diff --git a/test/jdk/java/lang/ProcessBuilder/FDLeakTest/exeFDLeakTester.c b/test/jdk/java/lang/ProcessBuilder/FDLeakTest/exeFDLeakTester.c new file mode 100644 index 00000000000..b47228ee5de --- /dev/null +++ b/test/jdk/java/lang/ProcessBuilder/FDLeakTest/exeFDLeakTester.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include +#include + +/* Check if any fd past stderr is valid; if true, print warning on stderr and return -1 + * + * Note: check without accessing /proc since: + * - non-portable + * - may cause creation of temporary file descriptors + */ +int main(int argc, char** argv) { + int errors = 0; + int rc = 0; + char buf[128]; + int max_fd = (int)sysconf(_SC_OPEN_MAX); + if (max_fd == -1) { + snprintf(buf, sizeof(buf), "*** sysconf(_SC_OPEN_MAX) failed? (%d) ***\n", errno); + rc = write(2, buf, strlen(buf)); + max_fd = 10000; + } + // We start after stderr fd + for (int fd = 3; fd < max_fd; fd++) { + if (fcntl(fd, F_GETFD, 0) >= 0) { + // Error: found valid file descriptor + errors++; + snprintf(buf, sizeof(buf), "*** Parent leaked file descriptor %d ***\n", fd); + rc = write(2, buf, strlen(buf)); + } + } + return errors > 0 ? -1 : 0; +} diff --git a/test/jdk/java/lang/ProcessBuilder/FDLeakTest/libFDLeaker.c b/test/jdk/java/lang/ProcessBuilder/FDLeakTest/libFDLeaker.c new file mode 100644 index 00000000000..b3fa296cae2 --- /dev/null +++ b/test/jdk/java/lang/ProcessBuilder/FDLeakTest/libFDLeaker.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include "jvmti.h" + +JNIEXPORT jint JNICALL +Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { + const char* filename = "./testfile_FDLeaker.txt"; + FILE* f = fopen(filename, "w"); + if (f == NULL) { + return JNI_ERR; + } + printf("Opened and leaked %s (%d)", filename, fileno(f)); + return JNI_OK; +} From 8c760e78b9e3851d40f8036105666e9c451b09a1 Mon Sep 17 00:00:00 2001 From: "lawrence.andrews" Date: Tue, 17 Jun 2025 20:42:42 +0000 Subject: [PATCH 090/213] 8359418: Test "javax/swing/text/GlyphView/bug4188841.java" failed because the phrase of text pane does not match the instructions Reviewed-by: honkar --- test/jdk/javax/swing/text/GlyphView/bug4188841.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/javax/swing/text/GlyphView/bug4188841.java b/test/jdk/javax/swing/text/GlyphView/bug4188841.java index 1b3cc0bcdd4..9935712bd49 100644 --- a/test/jdk/javax/swing/text/GlyphView/bug4188841.java +++ b/test/jdk/javax/swing/text/GlyphView/bug4188841.java @@ -69,7 +69,7 @@ static JFrame createUI() { JFrame frame = new JFrame("bug4188841"); NoWrapTextPane nwp = new NoWrapTextPane(); - nwp.setText("the\tslow\tbrown\tfox\tjumps\tover\tthe\tlazy\tdog!"); + nwp.setText("the\tquick\tbrown\tfox\tjumps\tover\tthe\tlazy\tdog!"); nwp.setCaretPosition(nwp.getText().length()); JScrollPane scrollPane = new JScrollPane(nwp, From 382f870cd53d69dfc1d2b96150aa2c026e47f642 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Tue, 17 Jun 2025 21:15:25 +0000 Subject: [PATCH 091/213] 8357976: GenShen crash in swap_card_tables: Should be clean Reviewed-by: kdnilsen, cslucas, ysr, xpeng --- .../share/gc/shenandoah/shenandoahConcurrentGC.cpp | 8 ++++---- .../share/gc/shenandoah/shenandoahDegeneratedGC.cpp | 12 +++++++++--- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 5b5fe2c1af6..fda97c4836e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -415,10 +415,6 @@ void ShenandoahConcurrentGC::entry_reset() { msg); op_reset(); } - - if (heap->mode()->is_generational()) { - heap->old_generation()->card_scan()->mark_read_table_as_clean(); - } } void ShenandoahConcurrentGC::entry_scan_remembered_set() { @@ -644,6 +640,10 @@ void ShenandoahConcurrentGC::op_reset() { } else { _generation->prepare_gc(); } + + if (heap->mode()->is_generational()) { + heap->old_generation()->card_scan()->mark_read_table_as_clean(); + } } class ShenandoahInitMarkUpdateRegionStateClosure : public ShenandoahHeapRegionClosure { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp index 7aaf7bd9f48..c941379d576 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp @@ -136,9 +136,15 @@ void ShenandoahDegenGC::op_degenerated() { heap->set_unload_classes(_generation->heuristics()->can_unload_classes() && (!heap->mode()->is_generational() || _generation->is_global())); - if (heap->mode()->is_generational() && _generation->is_young()) { - // Swap remembered sets for young - _generation->swap_card_tables(); + if (heap->mode()->is_generational()) { + // Clean the read table before swapping it. The end goal here is to have a clean + // write table, and to have the read table updated with the previous write table. + heap->old_generation()->card_scan()->mark_read_table_as_clean(); + + if (_generation->is_young()) { + // Swap remembered sets for young + _generation->swap_card_tables(); + } } case _degenerated_roots: From 2f63d3aee555762bfaea2a77bf543a32ca43f069 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 18 Jun 2025 02:06:22 +0000 Subject: [PATCH 092/213] 7116990: (spec) Socket.connect(addr,timeout) not clear if IOException because of TCP timeout Reviewed-by: alanb, dfuchs --- src/java.base/share/classes/java/net/Socket.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/java.base/share/classes/java/net/Socket.java b/src/java.base/share/classes/java/net/Socket.java index 2905a51b402..692c3395f78 100644 --- a/src/java.base/share/classes/java/net/Socket.java +++ b/src/java.base/share/classes/java/net/Socket.java @@ -621,6 +621,13 @@ public void connect(SocketAddress endpoint) throws IOException { * {@code SocketException} with the interrupt status set. * * + * @apiNote Establishing a TCP/IP connection is subject to connect timeout settings + * in the operating system. The typical operating system timeout is in the range of tens of + * seconds to minutes. If the operating system timeout expires before the + * {@code timeout} specified to this method then an {@code IOException} is thrown. + * The {@code timeout} specified to this method is typically a timeout value that is + * shorter than the operating system timeout. + * * @param endpoint the {@code SocketAddress} * @param timeout the timeout value to be used in milliseconds. * @throws IOException if an error occurs during the connection, the socket From 1130c1bc33cc9ab4acc6862d7738297afa017e8b Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 18 Jun 2025 02:56:48 +0000 Subject: [PATCH 093/213] 6798061: The removal of System.out.println from KeyboardManager Reviewed-by: prr --- .../share/classes/javax/swing/KeyboardManager.java | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/KeyboardManager.java b/src/java.desktop/share/classes/javax/swing/KeyboardManager.java index 5028f19caf2..2ba5749dcdc 100644 --- a/src/java.desktop/share/classes/javax/swing/KeyboardManager.java +++ b/src/java.desktop/share/classes/javax/swing/KeyboardManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,9 +118,6 @@ public void registerKeyStroke(KeyStroke k, JComponent c) { v.addElement(c); keyMap.put(k, v); } - } else { - System.out.println("Unexpected condition in registerKeyStroke"); - Thread.dumpStack(); } componentKeyStrokeMap.put(new ComponentKeyStrokePair(c,k), topContainer); @@ -208,11 +205,6 @@ public void unregisterKeyStroke(KeyStroke ks, JComponent c) { @SuppressWarnings("deprecation") public boolean fireKeyboardAction(KeyEvent e, boolean pressed, Container topAncestor) { - if (e.isConsumed()) { - System.out.println("Acquired pre-used event!"); - Thread.dumpStack(); - } - // There may be two keystrokes associated with a low-level key event; // in this case a keystroke made of an extended key code has a priority. KeyStroke ks; @@ -266,10 +258,6 @@ public boolean fireKeyboardAction(KeyEvent e, boolean pressed, Container topAnce return true; } } - } else { - System.out.println( "Unexpected condition in fireKeyboardAction " + tmp); - // This means that tmp wasn't null, a JComponent, or a Vector. What is it? - Thread.dumpStack(); } } From 2b94b70ef50675f7853c0cb6a61e60e6eb7d92ed Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 18 Jun 2025 05:08:06 +0000 Subject: [PATCH 094/213] 8359428: Test 'javax/swing/JTabbedPane/bug4499556.java' failed because after selecting one of L&F items, the test case automatically failed when clicking on L&F Menu button again Reviewed-by: abhiscxk --- test/jdk/javax/swing/JTabbedPane/bug4499556.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/jdk/javax/swing/JTabbedPane/bug4499556.java b/test/jdk/javax/swing/JTabbedPane/bug4499556.java index fe9d7dbbfde..f9150b339e2 100644 --- a/test/jdk/javax/swing/JTabbedPane/bug4499556.java +++ b/test/jdk/javax/swing/JTabbedPane/bug4499556.java @@ -89,9 +89,10 @@ public static void main(String[] args) throws Exception { } static volatile JTabbedPane pane; + static volatile JFrame frame; static JFrame createUI() { - JFrame frame = new JFrame("bug4499556"); + frame = new JFrame("bug4499556"); pane = getTabbedPane(); frame.add(pane); frame.add(getRightPanel(), BorderLayout.EAST); @@ -262,7 +263,7 @@ static boolean setLAF(String laf) { e.printStackTrace(); return false; } - SwingUtilities.updateComponentTreeUI(pane); + SwingUtilities.updateComponentTreeUI(frame); return true; } From 57266064a7bb995c3c614c19b936687af35e9aa4 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 18 Jun 2025 09:03:25 +0000 Subject: [PATCH 095/213] 8359709: java.net.HttpURLConnection sends unexpected "Host" request header in some cases after JDK-8344190 Reviewed-by: dfuchs, djelinski, michaelm, vyazici --- .../www/protocol/http/HttpURLConnection.java | 8 +- .../net/HttpURLConnection/HostHeaderTest.java | 143 ++++++++++++++++++ 2 files changed, 147 insertions(+), 4 deletions(-) create mode 100644 test/jdk/java/net/HttpURLConnection/HostHeaderTest.java diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 5d8e6f467aa..b66d9ddb8cb 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -621,10 +621,10 @@ private void writeRequests() throws IOException { if (port != -1 && port != url.getDefaultPort()) { host += ":" + String.valueOf(port); } - String reqHost = requests.findValue("Host"); - if (reqHost == null || !reqHost.equalsIgnoreCase(host)) { - requests.set("Host", host); - } + // if the "Host" header hasn't been explicitly set, then set its + // value to the one determined through the request URL + requests.setIfNotSet("Host", host); + requests.setIfNotSet("Accept", acceptString); /* diff --git a/test/jdk/java/net/HttpURLConnection/HostHeaderTest.java b/test/jdk/java/net/HttpURLConnection/HostHeaderTest.java new file mode 100644 index 00000000000..329f0eedaf9 --- /dev/null +++ b/test/jdk/java/net/HttpURLConnection/HostHeaderTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.URL; +import java.net.URLConnection; +import java.util.List; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import jdk.test.lib.net.URIBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertNull; + +/* + * @test + * @bug 8359709 + * @summary verify that if the Host header is allowed to be set by the application + * then the correct value gets set in a HTTP request issued through + * java.net.HttpURLConnection + * @library /test/lib + * @run junit HostHeaderTest + * @run junit/othervm -Dsun.net.http.allowRestrictedHeaders=true HostHeaderTest + * @run junit/othervm -Dsun.net.http.allowRestrictedHeaders=false HostHeaderTest + */ +class HostHeaderTest { + + private static final String SERVER_CTX_ROOT = "/8359709/"; + private static final boolean allowsHostHeader = Boolean.getBoolean("sun.net.http.allowRestrictedHeaders"); + + private static HttpServer server; + + @BeforeAll + static void beforeAll() throws Exception { + final InetSocketAddress addr = new InetSocketAddress(InetAddress.getLoopbackAddress(), 0); + server = HttpServer.create(addr, 0); + server.createContext(SERVER_CTX_ROOT, new Handler()); + server.start(); + System.err.println("started server at " + server.getAddress()); + } + + @AfterAll + static void afterAll() throws Exception { + if (server != null) { + System.err.println("stopping server " + server.getAddress()); + server.stop(0); + } + } + + @Test + void testHostHeader() throws Exception { + final InetSocketAddress serverAddr = server.getAddress(); + final URL reqURL = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(serverAddr.getPort()) + .path(SERVER_CTX_ROOT) + .build().toURL(); + final URLConnection conn = reqURL.openConnection(Proxy.NO_PROXY); + + conn.setRequestProperty("Host", "foobar"); + if (!allowsHostHeader) { + // if restricted headers aren't allowed to be set by the user, then + // we expect the previous call to setRequestProperty to not set the Host + // header + assertNull(conn.getRequestProperty("Host"), "Host header unexpectedly set"); + } + + assertInstanceOf(HttpURLConnection.class, conn); + final HttpURLConnection httpURLConn = (HttpURLConnection) conn; + + // send the HTTP request + System.err.println("sending request " + reqURL); + final int respCode = httpURLConn.getResponseCode(); + assertEquals(200, respCode, "unexpected response code"); + // verify that the server side handler received the expected + // Host header value in the request + try (final InputStream is = httpURLConn.getInputStream()) { + final byte[] resp = is.readAllBytes(); + // if Host header wasn't explicitly set, then we expect it to be + // derived from the request URL + final String expected = allowsHostHeader + ? "foobar" + : reqURL.getHost() + ":" + reqURL.getPort(); + final String actual = new String(resp, US_ASCII); + assertEquals(expected, actual, "unexpected Host header received on server side"); + } + } + + private static final class Handler implements HttpHandler { + private static final int NO_RESPONSE_BODY = -1; + + @Override + public void handle(final HttpExchange exchange) throws IOException { + final List headerVals = exchange.getRequestHeaders().get("Host"); + System.err.println("Host header has value(s): " + headerVals); + // unexpected Host header value, respond with 400 status code + if (headerVals == null || headerVals.size() != 1) { + System.err.println("Unexpected header value(s) for Host header: " + headerVals); + exchange.sendResponseHeaders(400, NO_RESPONSE_BODY); + return; + } + // respond back with the Host header value that we found in the request + final byte[] response = headerVals.getFirst().getBytes(US_ASCII); + exchange.sendResponseHeaders(200, response.length); + try (final OutputStream os = exchange.getResponseBody()) { + os.write(response); + } + } + } +} From cabd7c1f7a8c471d5461e3557fb589fdfe4d88be Mon Sep 17 00:00:00 2001 From: Matthew Donovan Date: Wed, 18 Jun 2025 11:24:54 +0000 Subject: [PATCH 096/213] 8356897: Update NSS library to 3.111 Reviewed-by: rhalade --- test/jdk/sun/security/pkcs11/PKCS11Test.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java index efae619314d..0f1da62efcc 100644 --- a/test/jdk/sun/security/pkcs11/PKCS11Test.java +++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java @@ -80,7 +80,7 @@ public abstract class PKCS11Test { // Version of the NSS artifact. This coincides with the version of // the NSS version - private static final String NSS_BUNDLE_VERSION = "3.107"; + private static final String NSS_BUNDLE_VERSION = "3.111"; private static final String NSSLIB = "jpg.tests.jdk.nsslib"; static double nss_version = -1; From f07f5ce9845c59348dc785cd5ee26391dd7e36c8 Mon Sep 17 00:00:00 2001 From: "He-Pin(kerr)" Date: Wed, 18 Jun 2025 11:26:00 +0000 Subject: [PATCH 097/213] 8359067: Fix typo in DelayScheduler.java Reviewed-by: syan, dl, rriggs, vklang --- .../share/classes/java/util/concurrent/DelayScheduler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/util/concurrent/DelayScheduler.java b/src/java.base/share/classes/java/util/concurrent/DelayScheduler.java index 358d3b69f1e..d1f8283489b 100644 --- a/src/java.base/share/classes/java/util/concurrent/DelayScheduler.java +++ b/src/java.base/share/classes/java/util/concurrent/DelayScheduler.java @@ -85,7 +85,7 @@ final class DelayScheduler extends Thread { * termination checks as well as to suppress reactivation after * terminating. * - * We avoid the need for auxilliary data structures by embedding + * We avoid the need for auxiliary data structures by embedding * pending queue links, heap indices, and pool references inside * ScheduledForkJoinTasks. (We use the same structure for both * Runnable and Callable versions, since including an extra field From 547ce0301684fdebe95ce2e8e195a019bcefe493 Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Wed, 18 Jun 2025 11:37:48 +0000 Subject: [PATCH 098/213] 8337217: Port VirtualMemoryTracker to use VMATree Reviewed-by: jsjolen, gziemski --- src/hotspot/share/nmt/memBaseline.cpp | 2 +- src/hotspot/share/nmt/memMapPrinter.cpp | 2 +- src/hotspot/share/nmt/memReporter.cpp | 44 +- src/hotspot/share/nmt/memTracker.cpp | 4 +- src/hotspot/share/nmt/memTracker.hpp | 16 +- src/hotspot/share/nmt/memoryFileTracker.cpp | 3 +- src/hotspot/share/nmt/memoryFileTracker.hpp | 2 +- src/hotspot/share/nmt/nmtTreap.hpp | 12 +- src/hotspot/share/nmt/nmtUsage.cpp | 3 +- src/hotspot/share/nmt/regionsTree.cpp | 57 ++ src/hotspot/share/nmt/regionsTree.hpp | 96 +++ src/hotspot/share/nmt/regionsTree.inline.hpp | 87 +++ src/hotspot/share/nmt/threadStackTracker.cpp | 5 +- .../share/nmt/virtualMemoryTracker.cpp | 707 ++++-------------- .../share/nmt/virtualMemoryTracker.hpp | 159 ++-- src/hotspot/share/nmt/vmatree.cpp | 12 +- src/hotspot/share/nmt/vmatree.hpp | 25 +- src/hotspot/share/opto/printinlining.cpp | 1 + src/hotspot/share/utilities/debug.cpp | 1 - .../share/utilities/nativeCallStack.hpp | 1 + .../gtest/nmt/test_nmt_reserved_region.cpp | 53 -- test/hotspot/gtest/nmt/test_nmt_treap.cpp | 14 +- test/hotspot/gtest/nmt/test_regions_tree.cpp | 131 ++++ test/hotspot/gtest/nmt/test_vmatree.cpp | 31 +- .../runtime/test_committed_virtualmemory.cpp | 71 +- .../runtime/test_virtualMemoryTracker.cpp | 222 +++--- .../Thread/TestAlwaysPreTouchStacks.java | 19 +- 27 files changed, 892 insertions(+), 888 deletions(-) create mode 100644 src/hotspot/share/nmt/regionsTree.cpp create mode 100644 src/hotspot/share/nmt/regionsTree.hpp create mode 100644 src/hotspot/share/nmt/regionsTree.inline.hpp delete mode 100644 test/hotspot/gtest/nmt/test_nmt_reserved_region.cpp create mode 100644 test/hotspot/gtest/nmt/test_regions_tree.cpp diff --git a/src/hotspot/share/nmt/memBaseline.cpp b/src/hotspot/share/nmt/memBaseline.cpp index 5f5431b765f..8661f91174a 100644 --- a/src/hotspot/share/nmt/memBaseline.cpp +++ b/src/hotspot/share/nmt/memBaseline.cpp @@ -160,7 +160,7 @@ bool MemBaseline::baseline_allocation_sites() { // Virtual memory allocation sites VirtualMemoryAllocationWalker virtual_memory_walker; - if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) { + if (!VirtualMemoryTracker::Instance::walk_virtual_memory(&virtual_memory_walker)) { return false; } diff --git a/src/hotspot/share/nmt/memMapPrinter.cpp b/src/hotspot/share/nmt/memMapPrinter.cpp index 515d3804638..41d977e9639 100644 --- a/src/hotspot/share/nmt/memMapPrinter.cpp +++ b/src/hotspot/share/nmt/memMapPrinter.cpp @@ -157,7 +157,7 @@ class CachedNMTInformation : public VirtualMemoryWalker { // Iterate all NMT virtual memory regions and fill this cache. bool fill_from_nmt() { - return VirtualMemoryTracker::walk_virtual_memory(this); + return VirtualMemoryTracker::Instance::walk_virtual_memory(this); } }; diff --git a/src/hotspot/share/nmt/memReporter.cpp b/src/hotspot/share/nmt/memReporter.cpp index f7d7e121462..c1c847a4f2e 100644 --- a/src/hotspot/share/nmt/memReporter.cpp +++ b/src/hotspot/share/nmt/memReporter.cpp @@ -22,6 +22,7 @@ * */ #include "cds/filemap.hpp" +#include "logging/log.hpp" #include "memory/metaspace.hpp" #include "memory/metaspaceUtils.hpp" #include "nmt/mallocTracker.hpp" @@ -29,6 +30,8 @@ #include "nmt/memReporter.hpp" #include "nmt/memTracker.hpp" #include "nmt/memoryFileTracker.hpp" +#include "nmt/regionsTree.hpp" +#include "nmt/regionsTree.inline.hpp" #include "nmt/threadStackTracker.hpp" #include "nmt/virtualMemoryTracker.hpp" #include "utilities/debug.hpp" @@ -432,34 +435,45 @@ void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* } if (all_committed) { - CommittedRegionIterator itr = reserved_rgn->iterate_committed_regions(); - const CommittedMemoryRegion* committed_rgn = itr.next(); - if (committed_rgn->size() == reserved_rgn->size() && committed_rgn->call_stack()->equals(*stack)) { - // One region spanning the entire reserved region, with the same stack trace. - // Don't print this regions because the "reserved and committed" line above - // already indicates that the region is committed. - assert(itr.next() == nullptr, "Unexpectedly more than one regions"); + bool reserved_and_committed = false; + VirtualMemoryTracker::Instance::tree()->visit_committed_regions(*reserved_rgn, + [&](CommittedMemoryRegion& committed_rgn) { + if (committed_rgn.equals(*reserved_rgn)) { + // One region spanning the entire reserved region, with the same stack trace. + // Don't print this regions because the "reserved and committed" line above + // already indicates that the region is committed. + reserved_and_committed = true; + return false; + } + return true; + }); + + if (reserved_and_committed) { return; } } - CommittedRegionIterator itr = reserved_rgn->iterate_committed_regions(); - const CommittedMemoryRegion* committed_rgn; - while ((committed_rgn = itr.next()) != nullptr) { + auto print_committed_rgn = [&](const CommittedMemoryRegion& crgn) { // Don't report if size is too small - if (amount_in_current_scale(committed_rgn->size()) == 0) continue; - stack = committed_rgn->call_stack(); + if (amount_in_current_scale(crgn.size()) == 0) return; + stack = crgn.call_stack(); out->cr(); INDENT_BY(8, - print_virtual_memory_region("committed", committed_rgn->base(), committed_rgn->size()); + print_virtual_memory_region("committed", crgn.base(), crgn.size()); if (stack->is_empty()) { out->cr(); } else { out->print_cr(" from"); - INDENT_BY(4, stack->print_on(out);) + INDENT_BY(4, _stackprinter.print_stack(stack);) } ) - } + }; + + VirtualMemoryTracker::Instance::tree()->visit_committed_regions(*reserved_rgn, + [&](CommittedMemoryRegion& crgn) { + print_committed_rgn(crgn); + return true; + }); } void MemDetailReporter::report_memory_file_allocations() { diff --git a/src/hotspot/share/nmt/memTracker.cpp b/src/hotspot/share/nmt/memTracker.cpp index b3d94ceabec..3d001bb0b11 100644 --- a/src/hotspot/share/nmt/memTracker.cpp +++ b/src/hotspot/share/nmt/memTracker.cpp @@ -71,7 +71,7 @@ void MemTracker::initialize() { _baseline.initialize(); if (!MallocTracker::initialize(level) || !MemoryFileTracker::Instance::initialize(level) || - !VirtualMemoryTracker::initialize(level)) { + !VirtualMemoryTracker::Instance::initialize(level)) { assert(false, "NMT initialization failed"); level = NMT_off; log_warning(nmt)("NMT initialization failed. NMT disabled."); @@ -126,7 +126,7 @@ void MemTracker::final_report(outputStream* output) { bool MemTracker::print_containing_region(const void* p, outputStream* out) { return enabled() && (MallocTracker::print_pointer_information(p, out) || - VirtualMemoryTracker::print_containing_region(p, out)); + VirtualMemoryTracker::Instance::print_containing_region(p, out)); } void MemTracker::report(bool summary_only, outputStream* output, size_t scale) { diff --git a/src/hotspot/share/nmt/memTracker.hpp b/src/hotspot/share/nmt/memTracker.hpp index c208a02054f..8898bf08fa5 100644 --- a/src/hotspot/share/nmt/memTracker.hpp +++ b/src/hotspot/share/nmt/memTracker.hpp @@ -132,7 +132,7 @@ class MemTracker : AllStatic { if (!enabled()) return; if (addr != nullptr) { NmtVirtualMemoryLocker nvml; - VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, mem_tag); + VirtualMemoryTracker::Instance::add_reserved_region((address)addr, size, stack, mem_tag); } } @@ -140,7 +140,7 @@ class MemTracker : AllStatic { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { - VirtualMemoryTracker::remove_released_region((address)addr, size); + VirtualMemoryTracker::Instance::remove_released_region((address)addr, size); } } @@ -148,7 +148,7 @@ class MemTracker : AllStatic { assert_post_init(); if (!enabled()) return; if (addr != nullptr) { - VirtualMemoryTracker::remove_uncommitted_region((address)addr, size); + VirtualMemoryTracker::Instance::remove_uncommitted_region((address)addr, size); } } @@ -158,8 +158,8 @@ class MemTracker : AllStatic { if (!enabled()) return; if (addr != nullptr) { NmtVirtualMemoryLocker nvml; - VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, mem_tag); - VirtualMemoryTracker::add_committed_region((address)addr, size, stack); + VirtualMemoryTracker::Instance::add_reserved_region((address)addr, size, stack, mem_tag); + VirtualMemoryTracker::Instance::add_committed_region((address)addr, size, stack); } } @@ -169,7 +169,7 @@ class MemTracker : AllStatic { if (!enabled()) return; if (addr != nullptr) { NmtVirtualMemoryLocker nvml; - VirtualMemoryTracker::add_committed_region((address)addr, size, stack); + VirtualMemoryTracker::Instance::add_committed_region((address)addr, size, stack); } } @@ -217,7 +217,7 @@ class MemTracker : AllStatic { if (!enabled()) return; if (addr != nullptr) { NmtVirtualMemoryLocker nvml; - VirtualMemoryTracker::split_reserved_region((address)addr, size, split, mem_tag, split_tag); + VirtualMemoryTracker::Instance::split_reserved_region((address)addr, size, split, mem_tag, split_tag); } } @@ -230,7 +230,7 @@ class MemTracker : AllStatic { if (!enabled()) return; if (addr != nullptr) { NmtVirtualMemoryLocker nvml; - VirtualMemoryTracker::set_reserved_region_type((address)addr, size, mem_tag); + VirtualMemoryTracker::Instance::set_reserved_region_tag((address)addr, size, mem_tag); } } diff --git a/src/hotspot/share/nmt/memoryFileTracker.cpp b/src/hotspot/share/nmt/memoryFileTracker.cpp index 4ffcb535e4b..49ef6ef70a0 100644 --- a/src/hotspot/share/nmt/memoryFileTracker.cpp +++ b/src/hotspot/share/nmt/memoryFileTracker.cpp @@ -73,7 +73,7 @@ void MemoryFileTracker::print_report_on(const MemoryFile* file, outputStream* st if (prev == nullptr) { // Must be first node. prev = current; - return; + return true; } #ifdef ASSERT if (broken_start != nullptr && prev->val().out.mem_tag() != current->val().in.mem_tag()) { @@ -96,6 +96,7 @@ void MemoryFileTracker::print_report_on(const MemoryFile* file, outputStream* st stream->cr(); } prev = current; + return true; }); #ifdef ASSERT if (broken_start != nullptr) { diff --git a/src/hotspot/share/nmt/memoryFileTracker.hpp b/src/hotspot/share/nmt/memoryFileTracker.hpp index cd7a3fb8593..7800b1a3ba6 100644 --- a/src/hotspot/share/nmt/memoryFileTracker.hpp +++ b/src/hotspot/share/nmt/memoryFileTracker.hpp @@ -28,8 +28,8 @@ #include "memory/allocation.hpp" #include "nmt/nmtCommon.hpp" #include "nmt/nmtNativeCallStackStorage.hpp" -#include "nmt/virtualMemoryTracker.hpp" #include "nmt/vmatree.hpp" +#include "nmt/virtualMemoryTracker.hpp" #include "runtime/os.inline.hpp" #include "utilities/growableArray.hpp" #include "utilities/nativeCallStack.hpp" diff --git a/src/hotspot/share/nmt/nmtTreap.hpp b/src/hotspot/share/nmt/nmtTreap.hpp index 7e4ad3df95b..13e759cbd3a 100644 --- a/src/hotspot/share/nmt/nmtTreap.hpp +++ b/src/hotspot/share/nmt/nmtTreap.hpp @@ -55,6 +55,7 @@ template class Treap { friend class NMTVMATreeTest; friend class NMTTreapTest; + friend class VMTWithVMATreeTest; public: class TreapNode { friend Treap; @@ -212,12 +213,13 @@ class Treap { seen_count++; if (last_seen == nullptr) { last_seen = node; - return; + return true; } if (COMPARATOR::cmp(last_seen->key(), node->key()) > 0) { failed = false; } last_seen = node; + return true; }); assert(seen_count == _node_count, "the number of visited nodes do not match with the number of stored nodes"); assert(!failed, "keys was not monotonically strongly increasing when visiting in order"); @@ -382,7 +384,9 @@ class Treap { head = head->left(); } head = to_visit.pop(); - f(head); + if (!f(head)) { + return; + } head = head->right(); } } @@ -409,7 +413,9 @@ class Treap { const int cmp_from = COMPARATOR::cmp(head->key(), from); const int cmp_to = COMPARATOR::cmp(head->key(), to); if (cmp_from >= 0 && cmp_to < 0) { - f(head); + if (!f(head)) { + return; + } } if (cmp_to < 0) { head = head->right(); diff --git a/src/hotspot/share/nmt/nmtUsage.cpp b/src/hotspot/share/nmt/nmtUsage.cpp index f8ca1b0e1fa..0d2aa40ea07 100644 --- a/src/hotspot/share/nmt/nmtUsage.cpp +++ b/src/hotspot/share/nmt/nmtUsage.cpp @@ -29,7 +29,6 @@ #include "nmt/nmtCommon.hpp" #include "nmt/nmtUsage.hpp" #include "nmt/threadStackTracker.hpp" -#include "nmt/virtualMemoryTracker.hpp" // Enabled all options for snapshot. const NMTUsageOptions NMTUsage::OptionsAll = { true, true, true }; @@ -48,7 +47,7 @@ void NMTUsage::walk_thread_stacks() { // much memory had been committed if they are backed by virtual memory. This // needs to happen before we take the snapshot of the virtual memory since it // will update this information. - VirtualMemoryTracker::snapshot_thread_stacks(); + VirtualMemoryTracker::Instance::snapshot_thread_stacks(); } void NMTUsage::update_malloc_usage() { diff --git a/src/hotspot/share/nmt/regionsTree.cpp b/src/hotspot/share/nmt/regionsTree.cpp new file mode 100644 index 00000000000..09686f52067 --- /dev/null +++ b/src/hotspot/share/nmt/regionsTree.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#include "nmt/regionsTree.hpp" + +VMATree::SummaryDiff RegionsTree::commit_region(address addr, size_t size, const NativeCallStack& stack) { + return commit_mapping((VMATree::position)addr, size, make_region_data(stack, mtNone), /*use tag inplace*/ true); +} + +VMATree::SummaryDiff RegionsTree::uncommit_region(address addr, size_t size) { + return uncommit_mapping((VMATree::position)addr, size, make_region_data(NativeCallStack::empty_stack(), mtNone)); +} + +#ifdef ASSERT +void RegionsTree::NodeHelper::print_on(outputStream* st) { + auto st_str = [&](VMATree::StateType s){ + return s == VMATree::StateType::Released ? "Rl" : + s == VMATree::StateType::Reserved ? "Rv" : "Cm"; + }; + st->print_cr("pos: " INTPTR_FORMAT " " + "%s, %s <|> %s, %s", + p2i((address)position()), + st_str(in_state()), + NMTUtil::tag_to_name(in_tag()), + st_str(out_state()), + NMTUtil::tag_to_name(out_tag()) + ); +} + +void RegionsTree::print_on(outputStream* st) { + visit_in_order([&](Node* node) { + NodeHelper curr(node); + curr.print_on(st); + return true; + }); +} +#endif \ No newline at end of file diff --git a/src/hotspot/share/nmt/regionsTree.hpp b/src/hotspot/share/nmt/regionsTree.hpp new file mode 100644 index 00000000000..7fdb4e6fd39 --- /dev/null +++ b/src/hotspot/share/nmt/regionsTree.hpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef NMT_REGIONSTREE_HPP +#define NMT_REGIONSTREE_HPP + +#include "logging/log.hpp" +#include "nmt/nmtCommon.hpp" +#include "nmt/vmatree.hpp" + + +class ReservedMemoryRegion; +class CommittedMemoryRegion; +// RegionsTree extends VMATree to add some more specific API and also defines a helper +// for processing the tree nodes in a shorter and more meaningful way. +class RegionsTree : public VMATree { + NativeCallStackStorage _ncs_storage; + bool _with_storage; + + public: + RegionsTree(bool with_storage) : VMATree() , _ncs_storage(with_storage), _with_storage(with_storage) { } + + ReservedMemoryRegion find_reserved_region(address addr); + + SummaryDiff commit_region(address addr, size_t size, const NativeCallStack& stack); + SummaryDiff uncommit_region(address addr, size_t size); + + using Node = VMATree::TreapNode; + + class NodeHelper { + Node* _node; + public: + NodeHelper() : _node(nullptr) { } + NodeHelper(Node* node) : _node(node) { } + inline bool is_valid() const { return _node != nullptr; } + inline void clear_node() { _node = nullptr; } + inline VMATree::position position() const { return _node->key(); } + inline bool is_committed_begin() const { return ((uint8_t)out_state() & (uint8_t)VMATree::StateType::Committed) >= 2; } + inline bool is_released_begin() const { return out_state() == VMATree::StateType::Released; } + inline bool is_reserved_begin() const { return ((uint8_t)out_state() & (uint8_t)VMATree::StateType::Reserved) == 1; } + inline VMATree::StateType in_state() const { return _node->val().in.type(); } + inline VMATree::StateType out_state() const { return _node->val().out.type(); } + inline size_t distance_from(const NodeHelper& other) const { + assert (position() > other.position(), "negative distance"); + return position() - other.position(); + } + inline NativeCallStackStorage::StackIndex out_stack_index() const { return _node->val().out.reserved_stack(); } + inline MemTag in_tag() const { return _node->val().in.mem_tag(); } + inline MemTag out_tag() const { return _node->val().out.mem_tag(); } + inline void set_in_tag(MemTag tag) { _node->val().in.set_tag(tag); } + inline void set_out_tag(MemTag tag) { _node->val().out.set_tag(tag); } + DEBUG_ONLY(void print_on(outputStream* st);) + }; + + DEBUG_ONLY(void print_on(outputStream* st);) + + template + void visit_committed_regions(const ReservedMemoryRegion& rgn, F func); + + template + void visit_reserved_regions(F func); + + inline RegionData make_region_data(const NativeCallStack& ncs, MemTag tag) { + return RegionData(_ncs_storage.push(ncs), tag); + } + + inline const NativeCallStack stack(NodeHelper& node) { + if (!_with_storage) { + return NativeCallStack::empty_stack(); + } + NativeCallStackStorage::StackIndex si = node.out_stack_index(); + return _ncs_storage.get(si); + } +}; + +#endif // NMT_REGIONSTREE_HPP \ No newline at end of file diff --git a/src/hotspot/share/nmt/regionsTree.inline.hpp b/src/hotspot/share/nmt/regionsTree.inline.hpp new file mode 100644 index 00000000000..f1b7319f5ca --- /dev/null +++ b/src/hotspot/share/nmt/regionsTree.inline.hpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef SHARE_NMT_REGIONSTREE_INLINE_HPP +#define SHARE_NMT_REGIONSTREE_INLINE_HPP + +#include "nmt/regionsTree.hpp" +#include "nmt/virtualMemoryTracker.hpp" + +template +void RegionsTree::visit_committed_regions(const ReservedMemoryRegion& rgn, F func) { + position start = (position)rgn.base(); + size_t end = reinterpret_cast(rgn.end()) + 1; + size_t comm_size = 0; + + NodeHelper prev; + visit_range_in_order(start, end, [&](Node* node) { + NodeHelper curr(node); + if (prev.is_valid() && prev.is_committed_begin()) { + CommittedMemoryRegion cmr((address)prev.position(), curr.distance_from(prev), stack(prev)); + if (!func(cmr)) { + return false; + } + } + prev = curr; + return true; + }); +} + +template +void RegionsTree::visit_reserved_regions(F func) { + NodeHelper begin_node, prev; + size_t rgn_size = 0; + + visit_in_order([&](Node* node) { + NodeHelper curr(node); + if (prev.is_valid()) { + rgn_size += curr.distance_from(prev); + } else { + begin_node = curr; + rgn_size = 0; + } + prev = curr; + if (curr.is_released_begin() || begin_node.out_tag() != curr.out_tag()) { + auto st = stack(begin_node); + if (rgn_size == 0) { + prev.clear_node(); + return true; + } + ReservedMemoryRegion rmr((address)begin_node.position(), rgn_size, st, begin_node.out_tag()); + if (!func(rmr)) { + return false; + } + rgn_size = 0; + if (!curr.is_released_begin()) { + begin_node = curr; + } else { + begin_node.clear_node(); + prev.clear_node(); + } + } + + return true; + }); +} + +#endif //SHARE_NMT_REGIONSTREE_INLINE_HPP diff --git a/src/hotspot/share/nmt/threadStackTracker.cpp b/src/hotspot/share/nmt/threadStackTracker.cpp index dabb23f0801..3e649d882c4 100644 --- a/src/hotspot/share/nmt/threadStackTracker.cpp +++ b/src/hotspot/share/nmt/threadStackTracker.cpp @@ -26,7 +26,6 @@ #include "nmt/memTracker.hpp" #include "nmt/threadStackTracker.hpp" -#include "nmt/virtualMemoryTracker.hpp" #include "runtime/os.hpp" #include "utilities/align.hpp" #include "utilities/debug.hpp" @@ -52,7 +51,7 @@ void ThreadStackTracker::new_thread_stack(void* base, size_t size, const NativeC align_thread_stack_boundaries_inward(base, size); MemTracker::NmtVirtualMemoryLocker nvml; - VirtualMemoryTracker::add_reserved_region((address)base, size, stack, mtThreadStack); + VirtualMemoryTracker::Instance::add_reserved_region((address)base, size, stack, mtThreadStack); _thread_count++; } @@ -62,7 +61,7 @@ void ThreadStackTracker::delete_thread_stack(void* base, size_t size) { align_thread_stack_boundaries_inward(base, size); MemTracker::NmtVirtualMemoryLocker nvml; - VirtualMemoryTracker::remove_released_region((address)base, size); + MemTracker::record_virtual_memory_release((address)base, size); _thread_count--; } diff --git a/src/hotspot/share/nmt/virtualMemoryTracker.cpp b/src/hotspot/share/nmt/virtualMemoryTracker.cpp index 04a72079460..51d8696a9ce 100644 --- a/src/hotspot/share/nmt/virtualMemoryTracker.cpp +++ b/src/hotspot/share/nmt/virtualMemoryTracker.cpp @@ -21,16 +21,16 @@ * questions. * */ + #include "logging/log.hpp" -#include "memory/metaspaceStats.hpp" -#include "memory/metaspaceUtils.hpp" #include "nmt/memTracker.hpp" -#include "nmt/nativeCallStackPrinter.hpp" -#include "nmt/threadStackTracker.hpp" #include "nmt/virtualMemoryTracker.hpp" +#include "nmt/regionsTree.hpp" +#include "nmt/regionsTree.inline.hpp" #include "runtime/os.hpp" #include "utilities/ostream.hpp" +VirtualMemoryTracker* VirtualMemoryTracker::Instance::_tracker = nullptr; VirtualMemorySnapshot VirtualMemorySummary::_snapshot; void VirtualMemory::update_peak(size_t size) { @@ -47,553 +47,206 @@ void VirtualMemory::update_peak(size_t size) { void VirtualMemorySummary::snapshot(VirtualMemorySnapshot* s) { // Snapshot current thread stacks - VirtualMemoryTracker::snapshot_thread_stacks(); + VirtualMemoryTracker::Instance::snapshot_thread_stacks(); as_snapshot()->copy_to(s); } -SortedLinkedList* VirtualMemoryTracker::_reserved_regions; - -int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) { - return r1.compare(r2); -} - -int compare_reserved_region_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) { - return r1.compare(r2); -} - -static bool is_mergeable_with(CommittedMemoryRegion* rgn, address addr, size_t size, const NativeCallStack& stack) { - return rgn->adjacent_to(addr, size) && rgn->call_stack()->equals(stack); -} - -static bool is_same_as(CommittedMemoryRegion* rgn, address addr, size_t size, const NativeCallStack& stack) { - // It would have made sense to use rgn->equals(...), but equals returns true for overlapping regions. - return rgn->same_region(addr, size) && rgn->call_stack()->equals(stack); -} - -static LinkedListNode* find_preceding_node_from(LinkedListNode* from, address addr) { - LinkedListNode* preceding = nullptr; - - for (LinkedListNode* node = from; node != nullptr; node = node->next()) { - CommittedMemoryRegion* rgn = node->data(); - - // We searched past the region start. - if (rgn->end() > addr) { - break; - } - - preceding = node; +bool VirtualMemoryTracker::Instance::initialize(NMT_TrackingLevel level) { + assert(_tracker == nullptr, "only call once"); + if (level >= NMT_summary) { + void* tracker = os::malloc(sizeof(VirtualMemoryTracker), mtNMT); + if (tracker == nullptr) return false; + _tracker = new (tracker) VirtualMemoryTracker(level == NMT_detail); } - - return preceding; + return true; } -static bool try_merge_with(LinkedListNode* node, address addr, size_t size, const NativeCallStack& stack) { - if (node != nullptr) { - CommittedMemoryRegion* rgn = node->data(); - if (is_mergeable_with(rgn, addr, size, stack)) { - rgn->expand_region(addr, size); - return true; - } - } - - return false; +void VirtualMemoryTracker::Instance::add_reserved_region(address base_addr, size_t size, + const NativeCallStack& stack, MemTag mem_tag) { + assert(_tracker != nullptr, "Sanity check"); + _tracker->add_reserved_region(base_addr, size, stack, mem_tag); } -static bool try_merge_with(LinkedListNode* node, LinkedListNode* other) { - if (other == nullptr) { - return false; - } - - CommittedMemoryRegion* rgn = other->data(); - return try_merge_with(node, rgn->base(), rgn->size(), *rgn->call_stack()); +void VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size, + const NativeCallStack& stack, MemTag mem_tag) { + VMATree::SummaryDiff diff = tree()->reserve_mapping((size_t)base_addr, size, tree()->make_region_data(stack, mem_tag)); + apply_summary_diff(diff); } -bool ReservedMemoryRegion::add_committed_region(address addr, size_t size, const NativeCallStack& stack) { - assert(addr != nullptr, "Invalid address"); - assert(size > 0, "Invalid size"); - assert(contain_region(addr, size), "Not contain this region"); - - // Find the region that fully precedes the [addr, addr + size) region. - LinkedListNode* prev = find_preceding_node_from(_committed_regions.head(), addr); - LinkedListNode* next = (prev != nullptr ? prev->next() : _committed_regions.head()); - - if (next != nullptr) { - // Ignore request if region already exists. - if (is_same_as(next->data(), addr, size, stack)) { - return true; - } - - // The new region is after prev, and either overlaps with the - // next region (and maybe more regions), or overlaps with no region. - if (next->data()->overlap_region(addr, size)) { - // Remove _all_ overlapping regions, and parts of regions, - // in preparation for the addition of this new region. - remove_uncommitted_region(addr, size); - - // The remove could have split a region into two and created a - // new prev region. Need to reset the prev and next pointers. - prev = find_preceding_node_from((prev != nullptr ? prev : _committed_regions.head()), addr); - next = (prev != nullptr ? prev->next() : _committed_regions.head()); - } - } - - // At this point the previous overlapping regions have been - // cleared, and the full region is guaranteed to be inserted. - VirtualMemorySummary::record_committed_memory(size, mem_tag()); - - // Try to merge with prev and possibly next. - if (try_merge_with(prev, addr, size, stack)) { - if (try_merge_with(prev, next)) { - // prev was expanded to contain the new region - // and next, need to remove next from the list - _committed_regions.remove_after(prev); - } - - return true; - } - - // Didn't merge with prev, try with next. - if (try_merge_with(next, addr, size, stack)) { - return true; - } - - // Couldn't merge with any regions - create a new region. - return add_committed_region(CommittedMemoryRegion(addr, size, stack)); +void VirtualMemoryTracker::Instance::set_reserved_region_tag(address addr, size_t size, MemTag mem_tag) { + assert(_tracker != nullptr, "Sanity check"); + _tracker->set_reserved_region_tag(addr, size, mem_tag); } -bool ReservedMemoryRegion::remove_uncommitted_region(LinkedListNode* node, - address addr, size_t size) { - assert(addr != nullptr, "Invalid address"); - assert(size > 0, "Invalid size"); - - CommittedMemoryRegion* rgn = node->data(); - assert(rgn->contain_region(addr, size), "Has to be contained"); - assert(!rgn->same_region(addr, size), "Can not be the same region"); - - if (rgn->base() == addr || - rgn->end() == addr + size) { - rgn->exclude_region(addr, size); - return true; - } else { - // split this region - address top =rgn->end(); - // use this region for lower part - size_t exclude_size = rgn->end() - addr; - rgn->exclude_region(addr, exclude_size); - - // higher part - address high_base = addr + size; - size_t high_size = top - high_base; - - CommittedMemoryRegion high_rgn(high_base, high_size, *rgn->call_stack()); - LinkedListNode* high_node = _committed_regions.add(high_rgn); - assert(high_node == nullptr || node->next() == high_node, "Should be right after"); - return (high_node != nullptr); - } - - return false; +void VirtualMemoryTracker::set_reserved_region_tag(address addr, size_t size, MemTag mem_tag) { + VMATree::SummaryDiff diff = tree()->set_tag((VMATree::position) addr, size, mem_tag); + apply_summary_diff(diff); } -bool ReservedMemoryRegion::remove_uncommitted_region(address addr, size_t sz) { - assert(addr != nullptr, "Invalid address"); - assert(sz > 0, "Invalid size"); - - CommittedMemoryRegion del_rgn(addr, sz, *call_stack()); - address end = addr + sz; - - LinkedListNode* head = _committed_regions.head(); - LinkedListNode* prev = nullptr; - CommittedMemoryRegion* crgn; - - while (head != nullptr) { - crgn = head->data(); - - if (crgn->same_region(addr, sz)) { - VirtualMemorySummary::record_uncommitted_memory(crgn->size(), mem_tag()); - _committed_regions.remove_after(prev); - return true; - } - - // del_rgn contains crgn - if (del_rgn.contain_region(crgn->base(), crgn->size())) { - VirtualMemorySummary::record_uncommitted_memory(crgn->size(), mem_tag()); - head = head->next(); - _committed_regions.remove_after(prev); - continue; // don't update head or prev - } - - // Found addr in the current crgn. There are 2 subcases: - if (crgn->contain_address(addr)) { +void VirtualMemoryTracker::Instance::apply_summary_diff(VMATree::SummaryDiff diff) { + assert(_tracker != nullptr, "Sanity check"); + _tracker->apply_summary_diff(diff); +} - // (1) Found addr+size in current crgn as well. (del_rgn is contained in crgn) - if (crgn->contain_address(end - 1)) { - VirtualMemorySummary::record_uncommitted_memory(sz, mem_tag()); - return remove_uncommitted_region(head, addr, sz); // done! +void VirtualMemoryTracker::apply_summary_diff(VMATree::SummaryDiff diff) { + VMATree::SingleDiff::delta reserve_delta, commit_delta; + size_t reserved, committed; + MemTag tag = mtNone; + auto print_err = [&](const char* str) { +#ifdef ASSERT + log_error(nmt)("summary mismatch, at %s, for %s," + " diff-reserved: %ld" + " diff-committed: %ld" + " vms-reserved: %zu" + " vms-committed: %zu", + str, NMTUtil::tag_to_name(tag), (long)reserve_delta, (long)commit_delta, reserved, committed); +#endif + }; + + for (int i = 0; i < mt_number_of_tags; i++) { + reserve_delta = diff.tag[i].reserve; + commit_delta = diff.tag[i].commit; + tag = NMTUtil::index_to_tag(i); + reserved = VirtualMemorySummary::as_snapshot()->by_tag(tag)->reserved(); + committed = VirtualMemorySummary::as_snapshot()->by_tag(tag)->committed(); + if (reserve_delta != 0) { + if (reserve_delta > 0) { + VirtualMemorySummary::record_reserved_memory(reserve_delta, tag); } else { - // (2) Did not find del_rgn's end in crgn. - size_t size = crgn->end() - del_rgn.base(); - crgn->exclude_region(addr, size); - VirtualMemorySummary::record_uncommitted_memory(size, mem_tag()); + if ((size_t)-reserve_delta <= reserved) { + VirtualMemorySummary::record_released_memory(-reserve_delta, tag); + } else { + print_err("release"); + } } - - } else if (crgn->contain_address(end - 1)) { - // Found del_rgn's end, but not its base addr. - size_t size = del_rgn.end() - crgn->base(); - crgn->exclude_region(crgn->base(), size); - VirtualMemorySummary::record_uncommitted_memory(size, mem_tag()); - return true; // should be done if the list is sorted properly! - } - - prev = head; - head = head->next(); - } - - return true; -} - -void ReservedMemoryRegion::move_committed_regions(address addr, ReservedMemoryRegion& rgn) { - assert(addr != nullptr, "Invalid address"); - - // split committed regions - LinkedListNode* head = - _committed_regions.head(); - LinkedListNode* prev = nullptr; - - while (head != nullptr) { - if (head->data()->base() >= addr) { - break; } - prev = head; - head = head->next(); - } - - if (head != nullptr) { - if (prev != nullptr) { - prev->set_next(head->next()); - } else { - _committed_regions.set_head(nullptr); + if (commit_delta != 0) { + if (commit_delta > 0) { + if ((size_t)commit_delta <= ((size_t)reserve_delta + reserved)) { + VirtualMemorySummary::record_committed_memory(commit_delta, tag); + } + else { + print_err("commit"); + } + } + else { + if ((size_t)-commit_delta <= committed) { + VirtualMemorySummary::record_uncommitted_memory(-commit_delta, tag); + } else { + print_err("uncommit"); + } + } } } - - rgn._committed_regions.set_head(head); } -size_t ReservedMemoryRegion::committed_size() const { - size_t committed = 0; - LinkedListNode* head = - _committed_regions.head(); - while (head != nullptr) { - committed += head->data()->size(); - head = head->next(); - } - return committed; -} - -void ReservedMemoryRegion::set_mem_tag(MemTag new_mem_tag) { - assert((mem_tag() == mtNone || mem_tag() == new_mem_tag), - "Overwrite memory tag for region [" INTPTR_FORMAT "-" INTPTR_FORMAT "), %u->%u.", - p2i(base()), p2i(end()), (unsigned)mem_tag(), (unsigned)new_mem_tag); - if (mem_tag() != new_mem_tag) { - VirtualMemorySummary::move_reserved_memory(mem_tag(), new_mem_tag, size()); - VirtualMemorySummary::move_committed_memory(mem_tag(), new_mem_tag, committed_size()); - _mem_tag = new_mem_tag; - } +void VirtualMemoryTracker::Instance::add_committed_region(address addr, size_t size, + const NativeCallStack& stack) { + assert(_tracker != nullptr, "Sanity check"); + _tracker->add_committed_region(addr, size, stack); } -address ReservedMemoryRegion::thread_stack_uncommitted_bottom() const { - assert(mem_tag() == mtThreadStack, "Only for thread stack"); - LinkedListNode* head = _committed_regions.head(); - address bottom = base(); - address top = base() + size(); - while (head != nullptr) { - address committed_top = head->data()->base() + head->data()->size(); - if (committed_top < top) { - // committed stack guard pages, skip them - bottom = head->data()->base() + head->data()->size(); - head = head->next(); - } else { - assert(top == committed_top, "Sanity"); - break; - } - } - - return bottom; +void VirtualMemoryTracker::add_committed_region(address addr, size_t size, + const NativeCallStack& stack) { + VMATree::SummaryDiff diff = tree()->commit_region(addr, size, stack); + apply_summary_diff(diff); } -bool VirtualMemoryTracker::initialize(NMT_TrackingLevel level) { - assert(_reserved_regions == nullptr, "only call once"); - if (level >= NMT_summary) { - _reserved_regions = new (std::nothrow, mtNMT) - SortedLinkedList(); - return (_reserved_regions != nullptr); - } - return true; +void VirtualMemoryTracker::Instance::remove_uncommitted_region(address addr, size_t size) { + assert(_tracker != nullptr, "Sanity check"); + _tracker->remove_uncommitted_region(addr, size); } -bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size, - const NativeCallStack& stack, MemTag mem_tag) { - assert(base_addr != nullptr, "Invalid address"); - assert(size > 0, "Invalid size"); - assert(_reserved_regions != nullptr, "Sanity check"); +void VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) { MemTracker::assert_locked(); - - ReservedMemoryRegion rgn(base_addr, size, stack, mem_tag); - ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); - - log_debug(nmt)("Add reserved region \'%s\' (" INTPTR_FORMAT ", %zu)", - rgn.mem_tag_name(), p2i(rgn.base()), rgn.size()); - if (reserved_rgn == nullptr) { - VirtualMemorySummary::record_reserved_memory(size, mem_tag); - return _reserved_regions->add(rgn) != nullptr; - } else { - // Deal with recursive reservation - // os::reserve_memory() -> pd_reserve_memory() -> os::reserve_memory() - // See JDK-8198226. - if (reserved_rgn->same_region(base_addr, size) && - (reserved_rgn->mem_tag() == mem_tag || reserved_rgn->mem_tag() == mtNone)) { - reserved_rgn->set_call_stack(stack); - reserved_rgn->set_mem_tag(mem_tag); - return true; - } else { - assert(reserved_rgn->overlap_region(base_addr, size), "Must be"); - - // Overlapped reservation. - // It can happen when the regions are thread stacks, as JNI - // thread does not detach from VM before exits, and leads to - // leak JavaThread object - if (reserved_rgn->mem_tag() == mtThreadStack) { - guarantee(!CheckJNICalls, "Attached JNI thread exited without being detached"); - // Overwrite with new region - - // Release old region - VirtualMemorySummary::record_uncommitted_memory(reserved_rgn->committed_size(), reserved_rgn->mem_tag()); - VirtualMemorySummary::record_released_memory(reserved_rgn->size(), reserved_rgn->mem_tag()); - - // Add new region - VirtualMemorySummary::record_reserved_memory(rgn.size(), mem_tag); - - *reserved_rgn = rgn; - return true; - } - - // CDS mapping region. - // CDS reserves the whole region for mapping CDS archive, then maps each section into the region. - // NMT reports CDS as a whole. - if (reserved_rgn->mem_tag() == mtClassShared) { - log_debug(nmt)("CDS reserved region \'%s\' as a whole (" INTPTR_FORMAT ", %zu)", - reserved_rgn->mem_tag_name(), p2i(reserved_rgn->base()), reserved_rgn->size()); - assert(reserved_rgn->contain_region(base_addr, size), "Reserved CDS region should contain this mapping region"); - return true; - } - - // Mapped CDS string region. - // The string region(s) is part of the java heap. - if (reserved_rgn->mem_tag() == mtJavaHeap) { - log_debug(nmt)("CDS reserved region \'%s\' as a whole (" INTPTR_FORMAT ", %zu)", - reserved_rgn->mem_tag_name(), p2i(reserved_rgn->base()), reserved_rgn->size()); - assert(reserved_rgn->contain_region(base_addr, size), "Reserved heap region should contain this mapping region"); - return true; - } - - if (reserved_rgn->mem_tag() == mtCode) { - assert(reserved_rgn->contain_region(base_addr, size), "Reserved code region should contain this mapping region"); - return true; - } - - // Print some more details. - stringStream ss; - ss.print_cr("Error: old region: [" INTPTR_FORMAT "-" INTPTR_FORMAT "), memory tag %s.\n" - " new region: [" INTPTR_FORMAT "-" INTPTR_FORMAT "), memory tag %s.", - p2i(reserved_rgn->base()), p2i(reserved_rgn->end()), NMTUtil::tag_to_name(reserved_rgn->mem_tag()), - p2i(base_addr), p2i(base_addr + size), NMTUtil::tag_to_name(mem_tag)); - if (MemTracker::tracking_level() == NMT_detail) { - ss.print_cr("Existing region allocated from:"); - reserved_rgn->call_stack()->print_on(&ss); - ss.print_cr("New region allocated from:"); - stack.print_on(&ss); - } - log_debug(nmt)("%s", ss.freeze()); - - ShouldNotReachHere(); - return false; - } - } + VMATree::SummaryDiff diff = tree()->uncommit_region(addr, size); + apply_summary_diff(diff); } -void VirtualMemoryTracker::set_reserved_region_type(address addr, size_t size, MemTag mem_tag) { - assert(addr != nullptr, "Invalid address"); - assert(_reserved_regions != nullptr, "Sanity check"); - MemTracker::assert_locked(); - - ReservedMemoryRegion rgn(addr, 1); - ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); - if (reserved_rgn != nullptr) { - assert(reserved_rgn->contain_address(addr), "Containment"); - if (reserved_rgn->mem_tag() != mem_tag) { - assert(reserved_rgn->mem_tag() == mtNone, "Overwrite memory tag (should be mtNone, is: \"%s\")", - NMTUtil::tag_to_name(reserved_rgn->mem_tag())); - reserved_rgn->set_mem_tag(mem_tag); - } - } +void VirtualMemoryTracker::Instance::remove_released_region(address addr, size_t size) { + assert(_tracker != nullptr, "Sanity check"); + _tracker->remove_released_region(addr, size); } -bool VirtualMemoryTracker::add_committed_region(address addr, size_t size, - const NativeCallStack& stack) { - assert(addr != nullptr, "Invalid address"); - assert(size > 0, "Invalid size"); - assert(_reserved_regions != nullptr, "Sanity check"); - MemTracker::assert_locked(); - - ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); - - if (reserved_rgn == nullptr) { - log_debug(nmt)("Add committed region \'%s\', No reserved region found for (" INTPTR_FORMAT ", %zu)", - rgn.mem_tag_name(), p2i(rgn.base()), rgn.size()); - } - assert(reserved_rgn != nullptr, "Add committed region, No reserved region found"); - assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); - bool result = reserved_rgn->add_committed_region(addr, size, stack); - log_debug(nmt)("Add committed region \'%s\'(" INTPTR_FORMAT ", %zu) %s", - reserved_rgn->mem_tag_name(), p2i(rgn.base()), rgn.size(), (result ? "Succeeded" : "Failed")); - return result; +void VirtualMemoryTracker::remove_released_region(address addr, size_t size) { + VMATree::SummaryDiff diff = tree()->release_mapping((VMATree::position)addr, size); + apply_summary_diff(diff); } -bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) { - assert(addr != nullptr, "Invalid address"); - assert(size > 0, "Invalid size"); - assert(_reserved_regions != nullptr, "Sanity check"); - MemTracker::assert_locked(); - - ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); - assert(reserved_rgn != nullptr, "No reserved region (" INTPTR_FORMAT ", %zu)", p2i(addr), size); - assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); - const char* type_name = reserved_rgn->mem_tag_name(); // after remove, info is not complete - bool result = reserved_rgn->remove_uncommitted_region(addr, size); - log_debug(nmt)("Removed uncommitted region \'%s\' (" INTPTR_FORMAT ", %zu) %s", - type_name, p2i(addr), size, (result ? " Succeeded" : "Failed")); - return result; +void VirtualMemoryTracker::Instance::split_reserved_region(address addr, size_t size, size_t split, MemTag mem_tag, MemTag split_mem_tag) { + assert(_tracker != nullptr, "Sanity check"); + _tracker->split_reserved_region(addr, size, split, mem_tag, split_mem_tag); } -bool VirtualMemoryTracker::remove_released_region(ReservedMemoryRegion* rgn) { - assert(rgn != nullptr, "Sanity check"); - assert(_reserved_regions != nullptr, "Sanity check"); - MemTracker::assert_locked(); - - // uncommit regions within the released region - ReservedMemoryRegion backup(*rgn); - bool result = rgn->remove_uncommitted_region(rgn->base(), rgn->size()); - log_debug(nmt)("Remove uncommitted region \'%s\' (" INTPTR_FORMAT ", %zu) %s", - backup.mem_tag_name(), p2i(backup.base()), backup.size(), (result ? "Succeeded" : "Failed")); - if (!result) { - return false; - } - - VirtualMemorySummary::record_released_memory(rgn->size(), rgn->mem_tag()); - result = _reserved_regions->remove(*rgn); - log_debug(nmt)("Removed region \'%s\' (" INTPTR_FORMAT ", %zu) from _reserved_regions %s" , - backup.mem_tag_name(), p2i(backup.base()), backup.size(), (result ? "Succeeded" : "Failed")); - return result; +void VirtualMemoryTracker::split_reserved_region(address addr, size_t size, size_t split, MemTag mem_tag, MemTag split_mem_tag) { + add_reserved_region(addr, split, NativeCallStack::empty_stack(), mem_tag); + add_reserved_region(addr + split, size - split, NativeCallStack::empty_stack(), split_mem_tag); } -bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) { - assert(addr != nullptr, "Invalid address"); - assert(size > 0, "Invalid size"); - assert(_reserved_regions != nullptr, "Sanity check"); - MemTracker::assert_locked(); - - ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); - - if (reserved_rgn == nullptr) { - log_debug(nmt)("No reserved region found for (" INTPTR_FORMAT ", %zu)!", - p2i(rgn.base()), rgn.size()); - } - assert(reserved_rgn != nullptr, "No reserved region"); - if (reserved_rgn->same_region(addr, size)) { - return remove_released_region(reserved_rgn); - } +bool VirtualMemoryTracker::Instance::print_containing_region(const void* p, outputStream* st) { + assert(_tracker != nullptr, "Sanity check"); + return _tracker->print_containing_region(p, st); +} - // uncommit regions within the released region - if (!reserved_rgn->remove_uncommitted_region(addr, size)) { +bool VirtualMemoryTracker::print_containing_region(const void* p, outputStream* st) { + ReservedMemoryRegion rmr = tree()->find_reserved_region((address)p); + if (!rmr.contain_address((address)p)) { return false; } - - if (reserved_rgn->mem_tag() == mtClassShared) { - if (reserved_rgn->contain_region(addr, size)) { - // This is an unmapped CDS region, which is part of the reserved shared - // memory region. - // See special handling in VirtualMemoryTracker::add_reserved_region also. - return true; - } - - if (size > reserved_rgn->size()) { - // This is from release the whole region spanning from archive space to class space, - // so we release them altogether. - ReservedMemoryRegion class_rgn(addr + reserved_rgn->size(), - (size - reserved_rgn->size())); - ReservedMemoryRegion* cls_rgn = _reserved_regions->find(class_rgn); - assert(cls_rgn != nullptr, "Class space region not recorded?"); - assert(cls_rgn->mem_tag() == mtClass, "Must be class mem tag"); - remove_released_region(reserved_rgn); - remove_released_region(cls_rgn); - return true; - } + st->print_cr(PTR_FORMAT " in mmap'd memory region [" PTR_FORMAT " - " PTR_FORMAT "], tag %s", + p2i(p), p2i(rmr.base()), p2i(rmr.end()), NMTUtil::tag_to_enum_name(rmr.mem_tag())); + if (MemTracker::tracking_level() == NMT_detail) { + rmr.call_stack()->print_on(st); } + st->cr(); + return true; +} - VirtualMemorySummary::record_released_memory(size, reserved_rgn->mem_tag()); +bool VirtualMemoryTracker::Instance::walk_virtual_memory(VirtualMemoryWalker* walker) { + assert(_tracker != nullptr, "Sanity check"); + return _tracker->walk_virtual_memory(walker); +} - assert(reserved_rgn->contain_region(addr, size), "Not completely contained"); - if (reserved_rgn->base() == addr || - reserved_rgn->end() == addr + size) { - reserved_rgn->exclude_region(addr, size); - return true; - } else { - address top = reserved_rgn->end(); - address high_base = addr + size; - ReservedMemoryRegion high_rgn(high_base, top - high_base, - *reserved_rgn->call_stack(), reserved_rgn->mem_tag()); - - // use original region for lower region - reserved_rgn->exclude_region(addr, top - addr); - LinkedListNode* new_rgn = _reserved_regions->add(high_rgn); - if (new_rgn == nullptr) { +bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { + MemTracker::NmtVirtualMemoryLocker nvml; + tree()->visit_reserved_regions([&](ReservedMemoryRegion& rgn) { + if (!walker->do_allocation_site(&rgn)) { return false; - } else { - reserved_rgn->move_committed_regions(addr, *new_rgn->data()); - return true; } - } + return true; + }); + return true; } -// Given an existing memory mapping registered with NMT, split the mapping in -// two. The newly created two mappings will be registered under the call -// stack and the memory tags of the original section. -bool VirtualMemoryTracker::split_reserved_region(address addr, size_t size, size_t split, MemTag mem_tag, MemTag split_tag) { - - ReservedMemoryRegion rgn(addr, size); - ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn); - assert(reserved_rgn->same_region(addr, size), "Must be identical region"); - assert(reserved_rgn != nullptr, "No reserved region"); - assert(reserved_rgn->committed_size() == 0, "Splitting committed region?"); - - NativeCallStack original_stack = *reserved_rgn->call_stack(); - MemTag original_tag = reserved_rgn->mem_tag(); +size_t ReservedMemoryRegion::committed_size() const { + size_t committed = 0; + size_t result = 0; + VirtualMemoryTracker::Instance::tree()->visit_committed_regions(*this, [&](CommittedMemoryRegion& crgn) { + result += crgn.size(); + return true; + }); + return result; +} - const char* name = reserved_rgn->mem_tag_name(); - remove_released_region(reserved_rgn); - log_debug(nmt)("Split region \'%s\' (" INTPTR_FORMAT ", %zu) with size %zu", - name, p2i(rgn.base()), rgn.size(), split); - // Now, create two new regions. - add_reserved_region(addr, split, original_stack, mem_tag); - add_reserved_region(addr + split, size - split, original_stack, split_tag); +address ReservedMemoryRegion::thread_stack_uncommitted_bottom() const { + address bottom = base(); + address top = base() + size(); + VirtualMemoryTracker::Instance::tree()->visit_committed_regions(*this, [&](CommittedMemoryRegion& crgn) { + address committed_top = crgn.base() + crgn.size(); + if (committed_top < top) { + // committed stack guard pages, skip them + bottom = crgn.base() + crgn.size(); + } else { + assert(top == committed_top, "Sanity, top=" INTPTR_FORMAT " , com-top=" INTPTR_FORMAT, p2i(top), p2i(committed_top)); + return false;; + } + return true; + }); - return true; + return bottom; } - // Iterate the range, find committed region within its bound. class RegionIterator : public StackObj { private: @@ -645,7 +298,6 @@ class SnapshotThreadStackWalker : public VirtualMemoryWalker { // Align the size to work with full pages (Alpine and AIX stack top is not page aligned) size_t aligned_stack_size = align_up(stack_size, os::vm_page_size()); - ReservedMemoryRegion* region = const_cast(rgn); NativeCallStack ncs; // empty stack RegionIterator itr(stack_bottom, aligned_stack_size); @@ -657,7 +309,7 @@ class SnapshotThreadStackWalker : public VirtualMemoryWalker { if (stack_bottom + stack_size < committed_start + committed_size) { committed_size = stack_bottom + stack_size - committed_start; } - region->add_committed_region(committed_start, committed_size, ncs); + VirtualMemoryTracker::Instance::add_committed_region(committed_start, committed_size, ncs); DEBUG_ONLY(found_stack = true;) } #ifdef ASSERT @@ -670,55 +322,24 @@ class SnapshotThreadStackWalker : public VirtualMemoryWalker { } }; -void VirtualMemoryTracker::snapshot_thread_stacks() { +void VirtualMemoryTracker::Instance::snapshot_thread_stacks() { SnapshotThreadStackWalker walker; walk_virtual_memory(&walker); } -bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) { - assert(_reserved_regions != nullptr, "Sanity check"); - MemTracker::NmtVirtualMemoryLocker nvml; - // Check that the _reserved_regions haven't been deleted. - if (_reserved_regions != nullptr) { - LinkedListNode* head = _reserved_regions->head(); - while (head != nullptr) { - const ReservedMemoryRegion* rgn = head->peek(); - if (!walker->do_allocation_site(rgn)) { +ReservedMemoryRegion RegionsTree::find_reserved_region(address addr) { + ReservedMemoryRegion rmr; + auto contain_region = [&](ReservedMemoryRegion& region_in_tree) { + if (region_in_tree.contain_address(addr)) { + rmr = region_in_tree; return false; } - head = head->next(); - } - } - return true; + return true; + }; + visit_reserved_regions(contain_region); + return rmr; } -class PrintRegionWalker : public VirtualMemoryWalker { -private: - const address _p; - outputStream* _st; - NativeCallStackPrinter _stackprinter; -public: - PrintRegionWalker(const void* p, outputStream* st) : - _p((address)p), _st(st), _stackprinter(st) { } - - bool do_allocation_site(const ReservedMemoryRegion* rgn) { - if (rgn->contain_address(_p)) { - _st->print_cr(PTR_FORMAT " in mmap'd memory region [" PTR_FORMAT " - " PTR_FORMAT "], tag %s", - p2i(_p), p2i(rgn->base()), p2i(rgn->base() + rgn->size()), NMTUtil::tag_to_enum_name(rgn->mem_tag())); - if (MemTracker::tracking_level() == NMT_detail) { - _stackprinter.print_stack(rgn->call_stack()); - _st->cr(); - } - return false; - } - return true; - } -}; - -// If p is contained within a known memory region, print information about it to the -// given stream and return true; false otherwise. -bool VirtualMemoryTracker::print_containing_region(const void* p, outputStream* st) { - PrintRegionWalker walker(p, st); - return !walk_virtual_memory(&walker); - -} +bool CommittedMemoryRegion::equals(const ReservedMemoryRegion& rmr) const { + return size() == rmr.size() && call_stack()->equals(*(rmr.call_stack())); +} \ No newline at end of file diff --git a/src/hotspot/share/nmt/virtualMemoryTracker.hpp b/src/hotspot/share/nmt/virtualMemoryTracker.hpp index 2b3b5722571..1c9628cd828 100644 --- a/src/hotspot/share/nmt/virtualMemoryTracker.hpp +++ b/src/hotspot/share/nmt/virtualMemoryTracker.hpp @@ -25,16 +25,29 @@ #ifndef SHARE_NMT_VIRTUALMEMORYTRACKER_HPP #define SHARE_NMT_VIRTUALMEMORYTRACKER_HPP -#include "memory/allocation.hpp" -#include "memory/metaspace.hpp" // For MetadataType -#include "memory/metaspaceStats.hpp" #include "nmt/allocationSite.hpp" -#include "nmt/nmtCommon.hpp" +#include "nmt/vmatree.hpp" +#include "nmt/regionsTree.hpp" #include "runtime/atomic.hpp" -#include "utilities/linkedlist.hpp" #include "utilities/nativeCallStack.hpp" #include "utilities/ostream.hpp" +// VirtualMemoryTracker (VMT) is an internal class of the MemTracker. +// All the Hotspot code use only the MemTracker interface to register the memory operations in NMT. +// Memory regions can be reserved/committed/uncommitted/released by calling MemTracker API which in turn call the corresponding functions in VMT. +// VMT uses RegionsTree to hold and manage the memory regions. Each region has two nodes that each one has address of the region (start/end) and +// state (reserved/released/committed) and MemTag of the regions before and after it. +// +// The memory operations of Reserve/Commit/Uncommit/Release are tracked by updating/inserting/deleting the nodes in the tree. When an operation +// changes nodes in the tree, the summary of the changes is returned back in a SummaryDiff struct. This struct shows that how much reserve/commit amount +// of any specific MemTag is changed. The summary of every operation is accumulated in VirtualMemorySummary class. +// +// Not all operations are valid in VMT. The following predicates are checked before the operation is applied to the tree and/or VirtualMemorySummary: +// - committed size of a MemTag should be <= of its reserved size +// - uncommitted size of a MemTag should be <= of its committed size +// - released size of a MemTag should be <= of its reserved size + + /* * Virtual memory counter */ @@ -276,136 +289,124 @@ class CommittedMemoryRegion : public VirtualMemoryRegion { NativeCallStack _stack; public: - CommittedMemoryRegion(address addr, size_t size, const NativeCallStack& stack) : - VirtualMemoryRegion(addr, size), _stack(stack) { } + CommittedMemoryRegion() + : VirtualMemoryRegion((address)1, 1), _stack(NativeCallStack::empty_stack()) { } + + CommittedMemoryRegion(address addr, size_t size, const NativeCallStack& stack) + : VirtualMemoryRegion(addr, size), _stack(stack) { } inline void set_call_stack(const NativeCallStack& stack) { _stack = stack; } inline const NativeCallStack* call_stack() const { return &_stack; } + bool equals(const ReservedMemoryRegion& other) const; }; - -typedef LinkedListIterator CommittedRegionIterator; - -int compare_committed_region(const CommittedMemoryRegion&, const CommittedMemoryRegion&); class ReservedMemoryRegion : public VirtualMemoryRegion { private: - SortedLinkedList - _committed_regions; - NativeCallStack _stack; - MemTag _mem_tag; + MemTag _mem_tag; public: + bool is_valid() { return base() != (address)1 && size() != 1;} + + ReservedMemoryRegion() + : VirtualMemoryRegion((address)1, 1), _stack(NativeCallStack::empty_stack()), _mem_tag(mtNone) { } + ReservedMemoryRegion(address base, size_t size, const NativeCallStack& stack, - MemTag mem_tag) : - VirtualMemoryRegion(base, size), _stack(stack), _mem_tag(mem_tag) { } + MemTag mem_tag = mtNone) + : VirtualMemoryRegion(base, size), _stack(stack), _mem_tag(mem_tag) { } - ReservedMemoryRegion(address base, size_t size) : - VirtualMemoryRegion(base, size), _stack(NativeCallStack::empty_stack()), _mem_tag(mtNone) { } + ReservedMemoryRegion(address base, size_t size) + : VirtualMemoryRegion(base, size), _stack(NativeCallStack::empty_stack()), _mem_tag(mtNone) { } // Copy constructor - ReservedMemoryRegion(const ReservedMemoryRegion& rr) : - VirtualMemoryRegion(rr.base(), rr.size()) { + ReservedMemoryRegion(const ReservedMemoryRegion& rr) + : VirtualMemoryRegion(rr.base(), rr.size()) { *this = rr; } inline void set_call_stack(const NativeCallStack& stack) { _stack = stack; } inline const NativeCallStack* call_stack() const { return &_stack; } - void set_mem_tag(MemTag mem_tag); inline MemTag mem_tag() const { return _mem_tag; } // uncommitted thread stack bottom, above guard pages if there is any. address thread_stack_uncommitted_bottom() const; - bool add_committed_region(address addr, size_t size, const NativeCallStack& stack); - bool remove_uncommitted_region(address addr, size_t size); - - size_t committed_size() const; + size_t committed_size() const; - // move committed regions that higher than specified address to - // the new region - void move_committed_regions(address addr, ReservedMemoryRegion& rgn); - - CommittedRegionIterator iterate_committed_regions() const { - return CommittedRegionIterator(_committed_regions.head()); - } ReservedMemoryRegion& operator= (const ReservedMemoryRegion& other) { set_base(other.base()); set_size(other.size()); - _stack = *other.call_stack(); + _stack = *other.call_stack(); _mem_tag = other.mem_tag(); - _committed_regions.clear(); - - CommittedRegionIterator itr = other.iterate_committed_regions(); - const CommittedMemoryRegion* rgn = itr.next(); - while (rgn != nullptr) { - _committed_regions.add(*rgn); - rgn = itr.next(); - } return *this; } - const char* mem_tag_name() const { return NMTUtil::tag_to_name(_mem_tag); } - - private: - // The committed region contains the uncommitted region, subtract the uncommitted - // region from this committed region - bool remove_uncommitted_region(LinkedListNode* node, - address addr, size_t sz); - - bool add_committed_region(const CommittedMemoryRegion& rgn) { - assert(rgn.base() != nullptr, "Invalid base address"); - assert(size() > 0, "Invalid size"); - return _committed_regions.add(rgn) != nullptr; - } + const char* tag_name() const { return NMTUtil::tag_to_name(_mem_tag); } }; -int compare_reserved_region_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2); - class VirtualMemoryWalker : public StackObj { public: virtual bool do_allocation_site(const ReservedMemoryRegion* rgn) { return false; } }; -// Main class called from MemTracker to track virtual memory allocations, commits and releases. -class VirtualMemoryTracker : AllStatic { - friend class VirtualMemoryTrackerTest; - friend class CommittedVirtualMemoryTest; - public: - static bool initialize(NMT_TrackingLevel level); +class VirtualMemoryTracker { + RegionsTree _tree; - static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MemTag mem_tag); + public: + VirtualMemoryTracker(bool is_detailed_mode) : _tree(is_detailed_mode) { } - static bool add_committed_region (address base_addr, size_t size, const NativeCallStack& stack); - static bool remove_uncommitted_region (address base_addr, size_t size); - static bool remove_released_region (address base_addr, size_t size); - static bool remove_released_region (ReservedMemoryRegion* rgn); - static void set_reserved_region_type (address addr, size_t size, MemTag mem_tag); + void add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MemTag mem_tag = mtNone); + void add_committed_region (address base_addr, size_t size, const NativeCallStack& stack); + void remove_uncommitted_region (address base_addr, size_t size); + void remove_released_region (address base_addr, size_t size); + void set_reserved_region_tag (address addr, size_t size, MemTag mem_tag); // Given an existing memory mapping registered with NMT, split the mapping in // two. The newly created two mappings will be registered under the call - // stack and the memory tag of the original section. - static bool split_reserved_region(address addr, size_t size, size_t split, MemTag mem_tag, MemTag split_type); + // stack and the memory tags of the original section. + void split_reserved_region(address addr, size_t size, size_t split, MemTag mem_tag, MemTag split_mem_tag); // Walk virtual memory data structure for creating baseline, etc. - static bool walk_virtual_memory(VirtualMemoryWalker* walker); + bool walk_virtual_memory(VirtualMemoryWalker* walker); // If p is contained within a known memory region, print information about it to the // given stream and return true; false otherwise. - static bool print_containing_region(const void* p, outputStream* st); + bool print_containing_region(const void* p, outputStream* st); // Snapshot current thread stacks - static void snapshot_thread_stacks(); - - private: - static SortedLinkedList* _reserved_regions; + void snapshot_thread_stacks(); + void apply_summary_diff(VMATree::SummaryDiff diff); + RegionsTree* tree() { return &_tree; } + + class Instance : public AllStatic { + friend class VirtualMemoryTrackerTest; + friend class CommittedVirtualMemoryTest; + + static VirtualMemoryTracker* _tracker; + + public: + using RegionData = VMATree::RegionData; + static bool initialize(NMT_TrackingLevel level); + + static void add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack, MemTag mem_tag = mtNone); + static void add_committed_region (address base_addr, size_t size, const NativeCallStack& stack); + static void remove_uncommitted_region (address base_addr, size_t size); + static void remove_released_region (address base_addr, size_t size); + static void set_reserved_region_tag (address addr, size_t size, MemTag mem_tag); + static void split_reserved_region(address addr, size_t size, size_t split, MemTag mem_tag, MemTag split_mem_tag); + static bool walk_virtual_memory(VirtualMemoryWalker* walker); + static bool print_containing_region(const void* p, outputStream* st); + static void snapshot_thread_stacks(); + static void apply_summary_diff(VMATree::SummaryDiff diff); + + static RegionsTree* tree() { return _tracker->tree(); } + }; }; -#endif // SHARE_NMT_VIRTUALMEMORYTRACKER_HPP - +#endif // SHARE_NMT_VIRTUALMEMORYTRACKER_HPP \ No newline at end of file diff --git a/src/hotspot/share/nmt/vmatree.cpp b/src/hotspot/share/nmt/vmatree.cpp index 48febdce7c2..a60c30c812d 100644 --- a/src/hotspot/share/nmt/vmatree.cpp +++ b/src/hotspot/share/nmt/vmatree.cpp @@ -82,8 +82,8 @@ const VMATree::RegionData VMATree::empty_regiondata{NativeCallStackStorage::invalid, mtNone}; -const char* VMATree::statetype_strings[3] = { - "released", "reserved", "committed" +const char* VMATree::statetype_strings[4] = { + "released","reserved", "only-committed", "committed", }; VMATree::SIndex VMATree::get_new_reserve_callstack(const SIndex es, const StateType ex, const RequestInfo& req) const { @@ -241,6 +241,7 @@ void VMATree::update_region(TreapNode* n1, TreapNode* n2, const RequestInfo& req compute_summary_diff(region_size, existing_tag, existing_state, req, new_tag, diff); } + VMATree::SummaryDiff VMATree::register_mapping(position _A, position _B, StateType state, const RegionData& metadata, bool use_tag_inplace) { @@ -344,7 +345,7 @@ VMATree::SummaryDiff VMATree::register_mapping(position _A, position _B, StateTy return false; }; GrowableArrayCHeap to_be_removed; - // update regions in [Y,W) + // update regions in range A to B auto update_loop = [&]() { TreapNode* prev = nullptr; _tree.visit_range_in_order(_A + 1, _B + 1, [&](TreapNode* curr) { @@ -357,6 +358,7 @@ VMATree::SummaryDiff VMATree::register_mapping(position _A, position _B, StateTy } } prev = curr; + return true; }); }; // update region of [A,T) @@ -416,8 +418,7 @@ VMATree::SummaryDiff VMATree::register_mapping(position _A, position _B, StateTy if ( X_eq_A && Y_exists && !Y_eq_W && !W_eq_B && U_exists) { row = 22; } if ( X_eq_A && Y_exists && W_eq_B && U_exists) { row = 23; } - DEBUG_ONLY(print_case();) - switch(row) { + switch(row) { // row 0: .........A..................B..... case 0: { update_A(B); @@ -652,6 +653,7 @@ void VMATree::print_on(outputStream* out) { visit_in_order([&](TreapNode* current) { out->print("%zu (%s) - %s [%d, %d]-> ", current->key(), NMTUtil::tag_to_name(out_state(current).mem_tag()), statetype_to_string(out_state(current).type()), current->val().out.reserved_stack(), current->val().out.committed_stack()); + return true; }); out->cr(); } diff --git a/src/hotspot/share/nmt/vmatree.hpp b/src/hotspot/share/nmt/vmatree.hpp index d3bf3724c0e..7f52b406309 100644 --- a/src/hotspot/share/nmt/vmatree.hpp +++ b/src/hotspot/share/nmt/vmatree.hpp @@ -26,6 +26,7 @@ #ifndef SHARE_NMT_VMATREE_HPP #define SHARE_NMT_VMATREE_HPP +#include "nmt/memTag.hpp" #include "nmt/memTag.hpp" #include "nmt/nmtNativeCallStackStorage.hpp" #include "nmt/nmtTreap.hpp" @@ -40,6 +41,7 @@ // The set of points is stored in a balanced binary tree for efficient querying and updating. class VMATree { friend class NMTVMATreeTest; + friend class VMTWithVMATreeTest; // A position in memory. public: using position = size_t; @@ -56,16 +58,18 @@ class VMATree { } }; - enum class StateType : uint8_t { Released, Reserved, Committed, LAST }; + // Bit fields view: bit 0 for Reserved, bit 1 for Committed. + // Setting a region as Committed preserves the Reserved state. + enum class StateType : uint8_t { Reserved = 1, Committed = 3, Released = 0, st_number_of_states = 4 }; private: - static const char* statetype_strings[static_cast(StateType::LAST)]; + static const char* statetype_strings[static_cast(StateType::st_number_of_states)]; public: NONCOPYABLE(VMATree); static const char* statetype_to_string(StateType type) { - assert(type != StateType::LAST, "must be"); + assert(type < StateType::st_number_of_states, "must be"); return statetype_strings[static_cast(type)]; } @@ -304,12 +308,8 @@ class VMATree { return register_mapping(from, from + size, StateType::Reserved, metadata, true); } - SummaryDiff release_mapping(position from, size size) { - return register_mapping(from, from + size, StateType::Released, VMATree::empty_regiondata); - } - - VMATreap& tree() { - return _tree; + SummaryDiff release_mapping(position from, position sz) { + return register_mapping(from, from + sz, StateType::Released, VMATree::empty_regiondata); } public: @@ -321,7 +321,10 @@ class VMATree { #ifdef ASSERT void print_on(outputStream* out); #endif - + template + void visit_range_in_order(const position& from, const position& to, F f) { + _tree.visit_range_in_order(from, to, f); + } + VMATreap& tree() { return _tree; } }; - #endif diff --git a/src/hotspot/share/opto/printinlining.cpp b/src/hotspot/share/opto/printinlining.cpp index accc3dcc637..bd0242e7bf2 100644 --- a/src/hotspot/share/opto/printinlining.cpp +++ b/src/hotspot/share/opto/printinlining.cpp @@ -105,5 +105,6 @@ void InlinePrinter::IPInlineSite::dump(outputStream* tty, int level) const { _children.visit_in_order([=](auto* node) { node->val().dump(tty, level + 1); + return true; }); } diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index abe3d6757b5..2502f850b66 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -37,7 +37,6 @@ #include "memory/universe.hpp" #include "nmt/mallocTracker.hpp" #include "nmt/memTracker.hpp" -#include "nmt/virtualMemoryTracker.hpp" #include "oops/klass.inline.hpp" #include "oops/oop.inline.hpp" #include "runtime/atomic.hpp" diff --git a/src/hotspot/share/utilities/nativeCallStack.hpp b/src/hotspot/share/utilities/nativeCallStack.hpp index 3ab72d67eca..5038fe31aef 100644 --- a/src/hotspot/share/utilities/nativeCallStack.hpp +++ b/src/hotspot/share/utilities/nativeCallStack.hpp @@ -55,6 +55,7 @@ class MemTracker; class NativeCallStack : public StackObj { + friend class VMTWithVMATreeTest; private: address _stack[NMT_TrackingStackDepth]; static const NativeCallStack _empty_stack; diff --git a/test/hotspot/gtest/nmt/test_nmt_reserved_region.cpp b/test/hotspot/gtest/nmt/test_nmt_reserved_region.cpp deleted file mode 100644 index 2acf54ab4be..00000000000 --- a/test/hotspot/gtest/nmt/test_nmt_reserved_region.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2023 SAP SE. All rights reserved. - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "nmt/nmtCommon.hpp" -#include "nmt/memTracker.hpp" -#include "nmt/virtualMemoryTracker.hpp" -#include "runtime/os.hpp" -#include "unittest.hpp" - -// Tests the assignment operator of ReservedMemoryRegion -TEST_VM(NMT, ReservedRegionCopy) { - address dummy1 = (address)0x10000000; - NativeCallStack stack1(&dummy1, 1); - ReservedMemoryRegion region1(dummy1, os::vm_page_size(), stack1, mtThreadStack); - VirtualMemorySummary::record_reserved_memory(os::vm_page_size(), region1.mem_tag()); - region1.add_committed_region(dummy1, os::vm_page_size(), stack1); - address dummy2 = (address)0x20000000; - NativeCallStack stack2(&dummy2, 1); - ReservedMemoryRegion region2(dummy2, os::vm_page_size(), stack2, mtCode); - VirtualMemorySummary::record_reserved_memory(os::vm_page_size(), region2.mem_tag()); - region2.add_committed_region(dummy2, os::vm_page_size(), stack2); - - region2 = region1; - - CommittedRegionIterator itr = region2.iterate_committed_regions(); - const CommittedMemoryRegion* rgn = itr.next(); - ASSERT_EQ(rgn->base(), dummy1); // Now we should see dummy1 - ASSERT_EQ(region2.mem_tag(), mtThreadStack); // Should be correct memory tag - ASSERT_EQ(region2.call_stack()->get_frame(0), dummy1); // Check the stack - rgn = itr.next(); - ASSERT_EQ(rgn, (const CommittedMemoryRegion*)nullptr); // and nothing else -} diff --git a/test/hotspot/gtest/nmt/test_nmt_treap.cpp b/test/hotspot/gtest/nmt/test_nmt_treap.cpp index 094b3348fdf..bc8c24b592f 100644 --- a/test/hotspot/gtest/nmt/test_nmt_treap.cpp +++ b/test/hotspot/gtest/nmt/test_nmt_treap.cpp @@ -24,9 +24,9 @@ #include "memory/resourceArea.hpp" #include "nmt/nmtTreap.hpp" +#include "nmt/virtualMemoryTracker.hpp" #include "runtime/os.hpp" #include "unittest.hpp" - class NMTTreapTest : public testing::Test { public: struct Cmp { @@ -72,6 +72,7 @@ class NMTTreapTest : public testing::Test { treap.visit_in_order([&](TreapCHeap::TreapNode* node) { nums_seen.at(node->key())++; + return true; }); for (int i = 0; i < up_to; i++) { EXPECT_EQ(1, nums_seen.at(i)); @@ -161,6 +162,7 @@ TEST_VM_F(NMTTreapTest, TestVisitors) { treap.visit_range_in_order(0, 100, [&](Node* x) { EXPECT_TRUE(false) << "Empty treap has no nodes to visit"; + return true; }); // Single-element set @@ -168,12 +170,14 @@ TEST_VM_F(NMTTreapTest, TestVisitors) { int count = 0; treap.visit_range_in_order(0, 100, [&](Node* x) { count++; + return true; }); EXPECT_EQ(1, count); count = 0; treap.visit_in_order([&](Node* x) { count++; + return true; }); EXPECT_EQ(1, count); @@ -184,12 +188,14 @@ TEST_VM_F(NMTTreapTest, TestVisitors) { count = 0; treap.visit_range_in_order(0, 100, [&](Node* x) { count++; + return true; }); EXPECT_EQ(1, count); count = 0; treap.visit_in_order([&](Node* x) { count++; + return true; }); EXPECT_EQ(3, count); @@ -197,6 +203,7 @@ TEST_VM_F(NMTTreapTest, TestVisitors) { treap.upsert(0, 0); // This node should not be visited. treap.visit_range_in_order(0, 0, [&](Node* x) { EXPECT_TRUE(false) << "Empty visiting range should not visit any node"; + return true; }); treap.remove_all(); @@ -208,6 +215,7 @@ TEST_VM_F(NMTTreapTest, TestVisitors) { GrowableArray seen; treap.visit_range_in_order(0, 10, [&](Node* x) { seen.push(x->key()); + return true; }); EXPECT_EQ(10, seen.length()); for (int i = 0; i < 10; i++) { @@ -217,6 +225,7 @@ TEST_VM_F(NMTTreapTest, TestVisitors) { seen.clear(); treap.visit_in_order([&](Node* x) { seen.push(x->key()); + return true; }); EXPECT_EQ(11, seen.length()); for (int i = 0; i < 10; i++) { @@ -226,6 +235,7 @@ TEST_VM_F(NMTTreapTest, TestVisitors) { seen.clear(); treap.visit_range_in_order(10, 12, [&](Node* x) { seen.push(x->key()); + return true; }); EXPECT_EQ(1, seen.length()); EXPECT_EQ(10, seen.at(0)); @@ -241,6 +251,7 @@ TEST_VM_F(NMTTreapTest, TestVisitors) { GrowableArray seen; treap.visit_range_in_order(9, -1, [&](Node* x) { seen.push(x->key()); + return true; }); EXPECT_EQ(10, seen.length()); for (int i = 0; i < 10; i++) { @@ -250,6 +261,7 @@ TEST_VM_F(NMTTreapTest, TestVisitors) { treap.visit_in_order([&](Node* x) { seen.push(x->key()); + return true; }); EXPECT_EQ(10, seen.length()); for (int i = 0; i < 10; i++) { diff --git a/test/hotspot/gtest/nmt/test_regions_tree.cpp b/test/hotspot/gtest/nmt/test_regions_tree.cpp new file mode 100644 index 00000000000..394c863746e --- /dev/null +++ b/test/hotspot/gtest/nmt/test_regions_tree.cpp @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "memory/allocation.hpp" +#include "nmt/memTag.hpp" +#include "nmt/nmtNativeCallStackStorage.hpp" +#include "nmt/regionsTree.inline.hpp" +#include "nmt/virtualMemoryTracker.hpp" +#include "nmt/vmatree.hpp" +#include "runtime/os.hpp" +#include "unittest.hpp" + +class NMTRegionsTreeTest : public testing::Test { + public: + RegionsTree rt; + NMTRegionsTreeTest() : rt(true) { } +}; + +TEST_VM_F(NMTRegionsTreeTest, ReserveCommitTwice) { + NativeCallStack ncs; + VMATree::RegionData rd = rt.make_region_data(ncs, mtTest); + VMATree::RegionData rd2 = rt.make_region_data(ncs, mtGC); + VMATree::SummaryDiff diff; + diff = rt.reserve_mapping(0, 100, rd); + EXPECT_EQ(100, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + diff = rt.commit_region(0, 50, ncs); + diff = rt.reserve_mapping(0, 100, rd); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(-50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); + diff = rt.reserve_mapping(0, 100, rd2); + EXPECT_EQ(-100, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(100, diff.tag[NMTUtil::tag_to_index(mtGC)].reserve); + diff = rt.commit_region(0, 50, ncs); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtGC)].reserve); + EXPECT_EQ(50, diff.tag[NMTUtil::tag_to_index(mtGC)].commit); + diff = rt.commit_region(0, 50, ncs); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); +} + +TEST_VM_F(NMTRegionsTreeTest, CommitUncommitRegion) { + NativeCallStack ncs; + VMATree::RegionData rd = rt.make_region_data(ncs, mtTest); + rt.reserve_mapping(0, 100, rd); + VMATree::SummaryDiff diff = rt.commit_region(0, 50, ncs); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); + diff = rt.commit_region((address)60, 10, ncs); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(10, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); + diff = rt.uncommit_region(0, 50); + EXPECT_EQ(0, diff.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(-50, diff.tag[NMTUtil::tag_to_index(mtTest)].commit); +} + +TEST_VM_F(NMTRegionsTreeTest, FindReservedRegion) { + NativeCallStack ncs; + VMATree::RegionData rd = rt.make_region_data(ncs, mtTest); + rt.reserve_mapping(1000, 50, rd); + rt.reserve_mapping(1200, 50, rd); + rt.reserve_mapping(1300, 50, rd); + rt.reserve_mapping(1400, 50, rd); + ReservedMemoryRegion rmr; + rmr = rt.find_reserved_region((address)1205); + EXPECT_EQ(rmr.base(), (address)1200); + rmr = rt.find_reserved_region((address)1305); + EXPECT_EQ(rmr.base(), (address)1300); + rmr = rt.find_reserved_region((address)1405); + EXPECT_EQ(rmr.base(), (address)1400); + rmr = rt.find_reserved_region((address)1005); + EXPECT_EQ(rmr.base(), (address)1000); +} + +TEST_VM_F(NMTRegionsTreeTest, VisitReservedRegions) { + NativeCallStack ncs; + VMATree::RegionData rd = rt.make_region_data(ncs, mtTest); + rt.reserve_mapping(1000, 50, rd); + rt.reserve_mapping(1200, 50, rd); + rt.reserve_mapping(1300, 50, rd); + rt.reserve_mapping(1400, 50, rd); + + rt.visit_reserved_regions([&](const ReservedMemoryRegion& rgn) { + EXPECT_EQ(((size_t)rgn.base()) % 100, 0UL); + EXPECT_EQ(rgn.size(), 50UL); + return true; + }); +} + +TEST_VM_F(NMTRegionsTreeTest, VisitCommittedRegions) { + NativeCallStack ncs; + VMATree::RegionData rd = rt.make_region_data(ncs, mtTest); + rt.reserve_mapping(1000, 50, rd); + rt.reserve_mapping(1200, 50, rd); + rt.reserve_mapping(1300, 50, rd); + rt.reserve_mapping(1400, 50, rd); + + rt.commit_region((address)1010, 5UL, ncs); + rt.commit_region((address)1020, 5UL, ncs); + rt.commit_region((address)1030, 5UL, ncs); + rt.commit_region((address)1040, 5UL, ncs); + ReservedMemoryRegion rmr((address)1000, 50); + size_t count = 0; + rt.visit_committed_regions(rmr, [&](CommittedMemoryRegion& crgn) { + count++; + EXPECT_EQ((((size_t)crgn.base()) % 100) / 10, count); + EXPECT_EQ(crgn.size(), 5UL); + return true; + }); + EXPECT_EQ(count, 4UL); +} \ No newline at end of file diff --git a/test/hotspot/gtest/nmt/test_vmatree.cpp b/test/hotspot/gtest/nmt/test_vmatree.cpp index 4d3418cc9fc..b43bfc58c69 100644 --- a/test/hotspot/gtest/nmt/test_vmatree.cpp +++ b/test/hotspot/gtest/nmt/test_vmatree.cpp @@ -24,6 +24,7 @@ #include "memory/allocation.hpp" #include "nmt/memTag.hpp" +#include "nmt/memTracker.hpp" #include "nmt/nmtNativeCallStackStorage.hpp" #include "nmt/vmatree.hpp" #include "runtime/os.hpp" @@ -82,6 +83,7 @@ class NMTVMATreeTest : public testing::Test { int count = 0; treap(tree).visit_in_order([&](TNode* x) { ++count; + return true; }); return count; } @@ -143,6 +145,7 @@ class NMTVMATreeTest : public testing::Test { VMATree::StateType out = out_type_of(x); EXPECT_TRUE((in == VMATree::StateType::Released && out == VMATree::StateType::Committed) || (in == VMATree::StateType::Committed && out == VMATree::StateType::Released)); + return true; }); EXPECT_EQ(2, count_nodes(tree)); } @@ -168,6 +171,7 @@ class NMTVMATreeTest : public testing::Test { found[i] = x->key(); } i++; + return true; }); ASSERT_EQ(4, i) << "0 - 50 - 75 - 100 nodes expected"; @@ -256,7 +260,6 @@ class NMTVMATreeTest : public testing::Test { } tree.tree().upsert((VMATree::position)et.nodes[i], st); } - print_tree(et, line_no); } template @@ -302,7 +305,6 @@ class NMTVMATreeTest : public testing::Test { EXPECT_FALSE(r.end->val().in.has_committed_stack()) << for_this_node; } } - print_tree(et, line_no); } template @@ -346,6 +348,16 @@ TEST_VM_F(NMTVMATreeTest, OverlappingReservationsResultInTwoNodes) { EXPECT_EQ(2, count_nodes(tree)); } +TEST_VM_F(NMTVMATreeTest, DuplicateReserve) { + VMATree::RegionData rd{si[0], mtTest}; + Tree tree; + tree.reserve_mapping(100, 100, rd); + tree.reserve_mapping(100, 100, rd); + EXPECT_EQ(2, count_nodes(tree)); + VMATree::VMATreap::Range r = tree.tree().find_enclosing_range(110); + EXPECT_EQ(100, (int)(r.end->key() - r.start->key())); +} + TEST_VM_F(NMTVMATreeTest, UseTagInplace) { Tree tree; VMATree::RegionData rd_Test_cs0(si[0], mtTest); @@ -364,6 +376,7 @@ TEST_VM_F(NMTVMATreeTest, UseTagInplace) { EXPECT_EQ(VMATree::StateType::Reserved, node->val().out.type()); } } + return true; }); } @@ -402,6 +415,7 @@ TEST_VM_F(NMTVMATreeTest, LowLevel) { if (x->key() == 0) { EXPECT_EQ(x->val().out.reserved_regiondata().mem_tag, mtTest); } + return true; }); EXPECT_EQ(2, count_nodes(tree)); @@ -441,6 +455,7 @@ TEST_VM_F(NMTVMATreeTest, LowLevel) { if (x->key() == 100) { EXPECT_EQ(mtTest, x->val().in.reserved_regiondata().mem_tag); } + return true; }); } @@ -796,6 +811,18 @@ TEST_VM_F(NMTVMATreeTest, SummaryAccounting) { } } +TEST_VM_F(NMTVMATreeTest, SummaryAccountingReserveAsUncommit) { + Tree tree; + Tree::RegionData rd(NCS::StackIndex(), mtTest); + VMATree::SummaryDiff diff1 = tree.reserve_mapping(1200, 100, rd); + VMATree::SummaryDiff diff2 = tree.commit_mapping(1210, 50, rd); + EXPECT_EQ(100, diff1.tag[NMTUtil::tag_to_index(mtTest)].reserve); + EXPECT_EQ(50, diff2.tag[NMTUtil::tag_to_index(mtTest)].commit); + VMATree::SummaryDiff diff3 = tree.reserve_mapping(1220, 20, rd); + EXPECT_EQ(-20, diff3.tag[NMTUtil::tag_to_index(mtTest)].commit); + EXPECT_EQ(0, diff3.tag[NMTUtil::tag_to_index(mtTest)].reserve); +} + // Exceedingly simple tracker for page-granular allocations // Use it for testing consistency with VMATree. struct SimpleVMATracker : public CHeapObj { diff --git a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp index f07b45bc32d..cd47e3a4e17 100644 --- a/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp +++ b/test/hotspot/gtest/runtime/test_committed_virtualmemory.cpp @@ -22,7 +22,8 @@ */ #include "nmt/memTracker.hpp" -#include "nmt/virtualMemoryTracker.hpp" +#include "nmt/regionsTree.hpp" +#include "nmt/regionsTree.inline.hpp" #include "runtime/thread.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -37,18 +38,15 @@ class CommittedVirtualMemoryTest { MemTracker::record_thread_stack(stack_end, stack_size); - VirtualMemoryTracker::add_reserved_region(stack_end, stack_size, CALLER_PC, mtThreadStack); + VirtualMemoryTracker::Instance::add_reserved_region(stack_end, stack_size, CALLER_PC, mtThreadStack); // snapshot current stack usage - VirtualMemoryTracker::snapshot_thread_stacks(); + VirtualMemoryTracker::Instance::snapshot_thread_stacks(); - ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(stack_end, stack_size)); - ASSERT_TRUE(rmr != nullptr); + ReservedMemoryRegion rmr_found = VirtualMemoryTracker::Instance::tree()->find_reserved_region(stack_end); + ASSERT_TRUE(rmr_found.is_valid()); + ASSERT_EQ(rmr_found.base(), stack_end); - ASSERT_EQ(rmr->base(), stack_end); - ASSERT_EQ(rmr->size(), stack_size); - - CommittedRegionIterator iter = rmr->iterate_committed_regions(); int i = 0; address i_addr = (address)&i; bool found_i_addr = false; @@ -56,24 +54,23 @@ class CommittedVirtualMemoryTest { // stack grows downward address stack_top = stack_end + stack_size; bool found_stack_top = false; - - for (const CommittedMemoryRegion* region = iter.next(); region != nullptr; region = iter.next()) { - if (region->base() + region->size() == stack_top) { - ASSERT_TRUE(region->size() <= stack_size); + VirtualMemoryTracker::Instance::tree()->visit_committed_regions(rmr_found, [&](const CommittedMemoryRegion& cmr) { + if (cmr.base() + cmr.size() == stack_top) { + EXPECT_TRUE(cmr.size() <= stack_size); found_stack_top = true; } - - if(i_addr < stack_top && i_addr >= region->base()) { + if(i_addr < stack_top && i_addr >= cmr.base()) { found_i_addr = true; } - i++; - } + return true; + }); + // stack and guard pages may be contiguous as one region ASSERT_TRUE(i >= 1); - ASSERT_TRUE(found_stack_top); ASSERT_TRUE(found_i_addr); + ASSERT_TRUE(found_stack_top); } static void check_covered_pages(address addr, size_t size, address base, size_t touch_pages, int* page_num) { @@ -100,28 +97,24 @@ class CommittedVirtualMemoryTest { *touch_addr = 'a'; } - address frame = (address)0x1235; - NativeCallStack stack(&frame, 1); - VirtualMemoryTracker::add_reserved_region((address)base, size, stack, mtThreadStack); - // trigger the test - VirtualMemoryTracker::snapshot_thread_stacks(); + VirtualMemoryTracker::Instance::snapshot_thread_stacks(); + + ReservedMemoryRegion rmr_found = VirtualMemoryTracker::Instance::tree()->find_reserved_region((address)base); + ASSERT_TRUE(rmr_found.is_valid()); + ASSERT_EQ(rmr_found.base(), (address)base); - ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion((address)base, size)); - ASSERT_TRUE(rmr != nullptr); bool precise_tracking_supported = false; - CommittedRegionIterator iter = rmr->iterate_committed_regions(); - for (const CommittedMemoryRegion* region = iter.next(); region != nullptr; region = iter.next()) { - if (region->size() == size) { - // platforms that do not support precise tracking. - ASSERT_TRUE(iter.next() == nullptr); - break; + VirtualMemoryTracker::Instance::tree()->visit_committed_regions(rmr_found, [&](const CommittedMemoryRegion& cmr){ + if (cmr.size() == size) { + return false; } else { precise_tracking_supported = true; - check_covered_pages(region->base(), region->size(), (address)base, touch_pages, page_num); + check_covered_pages(cmr.base(), cmr.size(), (address)base, touch_pages, page_num); } - } + return true; + }); if (precise_tracking_supported) { // All touched pages should be committed @@ -132,10 +125,9 @@ class CommittedVirtualMemoryTest { // Cleanup os::disclaim_memory(base, size); - VirtualMemoryTracker::remove_released_region((address)base, size); - - rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion((address)base, size)); - ASSERT_TRUE(rmr == nullptr); + VirtualMemoryTracker::Instance::remove_released_region((address)base, size); + rmr_found = VirtualMemoryTracker::Instance::tree()->find_reserved_region((address)base); + ASSERT_TRUE(!rmr_found.is_valid()); } static void test_committed_region() { @@ -233,8 +225,7 @@ class CommittedVirtualMemoryTest { } }; -TEST_VM(CommittedVirtualMemoryTracker, test_committed_virtualmemory_region) { - +TEST_VM(NMTCommittedVirtualMemoryTracker, test_committed_virtualmemory_region) { // This tests the VM-global NMT facility. The test must *not* modify global state, // since that interferes with other tests! // The gtestLauncher are called with and without -XX:NativeMemoryTracking during jtreg-controlled @@ -251,7 +242,7 @@ TEST_VM(CommittedVirtualMemoryTracker, test_committed_virtualmemory_region) { } #if !defined(_WINDOWS) && !defined(_AIX) -TEST_VM(CommittedVirtualMemory, test_committed_in_range){ +TEST_VM(NMTCommittedVirtualMemory, test_committed_in_range){ CommittedVirtualMemoryTest::test_committed_in_range(1024, 1024); CommittedVirtualMemoryTest::test_committed_in_range(2, 1); } diff --git a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp index 2985dd7438d..a6fee2c8fe1 100644 --- a/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp +++ b/test/hotspot/gtest/runtime/test_virtualMemoryTracker.cpp @@ -32,6 +32,7 @@ #include "memory/memoryReserver.hpp" #include "nmt/memTracker.hpp" +#include "nmt/regionsTree.inline.hpp" #include "nmt/virtualMemoryTracker.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" @@ -56,16 +57,15 @@ namespace { check_inner((rmr), nullptr, 0, __FILE__, __LINE__); \ } while (false) -static void diagnostic_print(ReservedMemoryRegion* rmr) { - CommittedRegionIterator iter = rmr->iterate_committed_regions(); - LOG("In reserved region " PTR_FORMAT ", size 0x%zx:", p2i(rmr->base()), rmr->size()); - for (const CommittedMemoryRegion* region = iter.next(); region != nullptr; region = iter.next()) { - LOG(" committed region: " PTR_FORMAT ", size 0x%zx", p2i(region->base()), region->size()); - } +static void diagnostic_print(const ReservedMemoryRegion& rmr) { + LOG("In reserved region " PTR_FORMAT ", size %X:", p2i(rmr.base()), rmr.size()); + VirtualMemoryTracker::Instance::tree()->visit_committed_regions(rmr, [&](CommittedMemoryRegion& region) { + LOG(" committed region: " PTR_FORMAT ", size %X", p2i(region.base()), region.size()); + return true; + }); } -static void check_inner(ReservedMemoryRegion* rmr, R* regions, size_t regions_size, const char* file, int line) { - CommittedRegionIterator iter = rmr->iterate_committed_regions(); +static void check_inner(const ReservedMemoryRegion& rmr, R* regions, size_t regions_size, const char* file, int line) { size_t i = 0; size_t size = 0; @@ -74,16 +74,17 @@ static void check_inner(ReservedMemoryRegion* rmr, R* regions, size_t regions_si #define WHERE " from " << file << ":" << line - for (const CommittedMemoryRegion* region = iter.next(); region != nullptr; region = iter.next()) { + VirtualMemoryTracker::Instance::tree()->visit_committed_regions(rmr, [&](CommittedMemoryRegion& region) { EXPECT_LT(i, regions_size) << WHERE; - EXPECT_EQ(region->base(), regions[i]._addr) << WHERE; - EXPECT_EQ(region->size(), regions[i]._size) << WHERE; - size += region->size(); + EXPECT_EQ(region.base(), regions[i]._addr) << WHERE; + EXPECT_EQ(region.size(), regions[i]._size) << WHERE; + size += region.size(); i++; - } + return true; + }); EXPECT_EQ(i, regions_size) << WHERE; - EXPECT_EQ(size, rmr->committed_size()) << WHERE; + EXPECT_EQ(size, rmr.committed_size()) << WHERE; } class VirtualMemoryTrackerTest { @@ -103,10 +104,11 @@ class VirtualMemoryTrackerTest { NativeCallStack stack2(&frame2, 1); // Fetch the added RMR for the space - ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size)); + ReservedMemoryRegion rmr = VirtualMemoryTracker::Instance::tree()->find_reserved_region(addr); + RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); - ASSERT_EQ(rmr->size(), size); - ASSERT_EQ(rmr->base(), addr); + ASSERT_EQ(rmr.size(), size); + ASSERT_EQ(rmr.base(), addr); // Commit Size Granularity const size_t cs = 0x1000; @@ -114,45 +116,45 @@ class VirtualMemoryTrackerTest { // Commit adjacent regions with same stack { // Commit one region - rmr->add_committed_region(addr + cs, cs, stack); + rtree->commit_region(addr + cs, cs, stack); R r[] = { {addr + cs, cs} }; check(rmr, r); } { // Commit adjacent - lower address - rmr->add_committed_region(addr, cs, stack); + rtree->commit_region(addr, cs, stack); R r[] = { {addr, 2 * cs} }; check(rmr, r); } { // Commit adjacent - higher address - rmr->add_committed_region(addr + 2 * cs, cs, stack); + rtree->commit_region(addr + 2 * cs, cs, stack); R r[] = { {addr, 3 * cs} }; check(rmr, r); } // Cleanup - rmr->remove_uncommitted_region(addr, 3 * cs); - ASSERT_EQ(rmr->committed_size(), 0u); + rtree->uncommit_region(addr, 3 * cs); + ASSERT_EQ(rmr.committed_size(), 0u); // Commit adjacent regions with different stacks { // Commit one region - rmr->add_committed_region(addr + cs, cs, stack); + rtree->commit_region(addr + cs, cs, stack); R r[] = { {addr + cs, cs} }; check(rmr, r); } { // Commit adjacent - lower address - rmr->add_committed_region(addr, cs, stack2); + rtree->commit_region(addr, cs, stack2); R r[] = { {addr, cs}, {addr + cs, cs} }; check(rmr, r); } { // Commit adjacent - higher address - rmr->add_committed_region(addr + 2 * cs, cs, stack2); + rtree->commit_region(addr + 2 * cs, cs, stack2); R r[] = { {addr, cs}, {addr + cs, cs}, {addr + 2 * cs, cs} }; @@ -160,11 +162,13 @@ class VirtualMemoryTrackerTest { } // Cleanup - rmr->remove_uncommitted_region(addr, 3 * cs); - ASSERT_EQ(rmr->committed_size(), 0u); + rtree->uncommit_region(addr, 3 * cs); + ASSERT_EQ(rmr.committed_size(), 0u); } static void test_add_committed_region_adjacent_overlapping() { + RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); + rtree->tree().remove_all(); size_t size = 0x01000000; ReservedSpace rs = MemoryReserver::reserve(size, mtTest); @@ -178,14 +182,11 @@ class VirtualMemoryTrackerTest { NativeCallStack stack(&frame1, 1); NativeCallStack stack2(&frame2, 1); - // Add the reserved memory - VirtualMemoryTracker::add_reserved_region(addr, size, stack, mtTest); - // Fetch the added RMR for the space - ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size)); + ReservedMemoryRegion rmr = rtree->find_reserved_region(addr); - ASSERT_EQ(rmr->size(), size); - ASSERT_EQ(rmr->base(), addr); + ASSERT_EQ(rmr.size(), size); + ASSERT_EQ(rmr.base(), addr); // Commit Size Granularity const size_t cs = 0x1000; @@ -193,46 +194,46 @@ class VirtualMemoryTrackerTest { // Commit adjacent and overlapping regions with same stack { // Commit two non-adjacent regions - rmr->add_committed_region(addr, 2 * cs, stack); - rmr->add_committed_region(addr + 3 * cs, 2 * cs, stack); + rtree->commit_region(addr, 2 * cs, stack); + rtree->commit_region(addr + 3 * cs, 2 * cs, stack); R r[] = { {addr, 2 * cs}, {addr + 3 * cs, 2 * cs} }; check(rmr, r); } { // Commit adjacent and overlapping - rmr->add_committed_region(addr + 2 * cs, 2 * cs, stack); + rtree->commit_region(addr + 2 * cs, 2 * cs, stack); R r[] = { {addr, 5 * cs} }; check(rmr, r); } // revert to two non-adjacent regions - rmr->remove_uncommitted_region(addr + 2 * cs, cs); - ASSERT_EQ(rmr->committed_size(), 4 * cs); + rtree->uncommit_region(addr + 2 * cs, cs); + ASSERT_EQ(rmr.committed_size(), 4 * cs); { // Commit overlapping and adjacent - rmr->add_committed_region(addr + cs, 2 * cs, stack); + rtree->commit_region(addr + cs, 2 * cs, stack); R r[] = { {addr, 5 * cs} }; check(rmr, r); } // Cleanup - rmr->remove_uncommitted_region(addr, 5 * cs); - ASSERT_EQ(rmr->committed_size(), 0u); + rtree->uncommit_region(addr, 5 * cs); + ASSERT_EQ(rmr.committed_size(), 0u); // Commit adjacent and overlapping regions with different stacks { // Commit two non-adjacent regions - rmr->add_committed_region(addr, 2 * cs, stack); - rmr->add_committed_region(addr + 3 * cs, 2 * cs, stack); + rtree->commit_region(addr, 2 * cs, stack); + rtree->commit_region(addr + 3 * cs, 2 * cs, stack); R r[] = { {addr, 2 * cs}, {addr + 3 * cs, 2 * cs} }; check(rmr, r); } { // Commit adjacent and overlapping - rmr->add_committed_region(addr + 2 * cs, 2 * cs, stack2); + rtree->commit_region(addr + 2 * cs, 2 * cs, stack2); R r[] = { {addr, 2 * cs}, {addr + 2 * cs, 2 * cs}, {addr + 4 * cs, cs} }; @@ -240,12 +241,12 @@ class VirtualMemoryTrackerTest { } // revert to two non-adjacent regions - rmr->add_committed_region(addr, 5 * cs, stack); - rmr->remove_uncommitted_region(addr + 2 * cs, cs); - ASSERT_EQ(rmr->committed_size(), 4 * cs); + rtree->commit_region(addr, 5 * cs, stack); + rtree->uncommit_region(addr + 2 * cs, cs); + ASSERT_EQ(rmr.committed_size(), 4 * cs); { // Commit overlapping and adjacent - rmr->add_committed_region(addr + cs, 2 * cs, stack2); + rtree->commit_region(addr + cs, 2 * cs, stack2); R r[] = { {addr, cs}, {addr + cs, 2 * cs}, {addr + 3 * cs, 2 * cs} }; @@ -254,6 +255,8 @@ class VirtualMemoryTrackerTest { } static void test_add_committed_region_overlapping() { + RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); + rtree->tree().remove_all(); size_t size = 0x01000000; @@ -269,10 +272,11 @@ class VirtualMemoryTrackerTest { NativeCallStack stack2(&frame2, 1); // Fetch the added RMR for the space - ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size)); + ReservedMemoryRegion rmr = rtree->find_reserved_region(addr); - ASSERT_EQ(rmr->size(), size); - ASSERT_EQ(rmr->base(), addr); + + ASSERT_EQ(rmr.size(), size); + ASSERT_EQ(rmr.base(), addr); // Commit Size Granularity const size_t cs = 0x1000; @@ -280,77 +284,77 @@ class VirtualMemoryTrackerTest { // With same stack { // Commit one region - rmr->add_committed_region(addr, cs, stack); + rtree->commit_region(addr, cs, stack); R r[] = { {addr, cs} }; check(rmr, r); } { // Commit the same region - rmr->add_committed_region(addr, cs, stack); + rtree->commit_region(addr, cs, stack); R r[] = { {addr, cs} }; check(rmr, r); } { // Commit a succeeding region - rmr->add_committed_region(addr + cs, cs, stack); + rtree->commit_region(addr + cs, cs, stack); R r[] = { {addr, 2 * cs} }; check(rmr, r); } { // Commit over two regions - rmr->add_committed_region(addr, 2 * cs, stack); + rtree->commit_region(addr, 2 * cs, stack); R r[] = { {addr, 2 * cs} }; check(rmr, r); } {// Commit first part of a region - rmr->add_committed_region(addr, cs, stack); + rtree->commit_region(addr, cs, stack); R r[] = { {addr, 2 * cs} }; check(rmr, r); } { // Commit second part of a region - rmr->add_committed_region(addr + cs, cs, stack); + rtree->commit_region(addr + cs, cs, stack); R r[] = { {addr, 2 * cs} }; check(rmr, r); } { // Commit a third part - rmr->add_committed_region(addr + 2 * cs, cs, stack); + rtree->commit_region(addr + 2 * cs, cs, stack); R r[] = { {addr, 3 * cs} }; check(rmr, r); } { // Commit in the middle of a region - rmr->add_committed_region(addr + 1 * cs, cs, stack); + rtree->commit_region(addr + 1 * cs, cs, stack); R r[] = { {addr, 3 * cs} }; check(rmr, r); } // Cleanup - rmr->remove_uncommitted_region(addr, 3 * cs); - ASSERT_EQ(rmr->committed_size(), 0u); + rtree->uncommit_region(addr, 3 * cs); + ASSERT_EQ(rmr.committed_size(), 0u); // With preceding region - rmr->add_committed_region(addr, cs, stack); - rmr->add_committed_region(addr + 2 * cs, 3 * cs, stack); + rtree->commit_region(addr, cs, stack); + rtree->commit_region(addr + 2 * cs, 3 * cs, stack); - rmr->add_committed_region(addr + 2 * cs, cs, stack); + rtree->commit_region(addr + 2 * cs, cs, stack); { R r[] = { {addr, cs}, {addr + 2 * cs, 3 * cs} }; check(rmr, r); } - rmr->add_committed_region(addr + 3 * cs, cs, stack); + rtree->commit_region(addr + 3 * cs, cs, stack); { R r[] = { {addr, cs}, {addr + 2 * cs, 3 * cs} }; check(rmr, r); } - rmr->add_committed_region(addr + 4 * cs, cs, stack); + rtree->commit_region(addr + 4 * cs, cs, stack); { R r[] = { {addr, cs}, {addr + 2 * cs, 3 * cs} }; @@ -358,57 +362,57 @@ class VirtualMemoryTrackerTest { } // Cleanup - rmr->remove_uncommitted_region(addr, 5 * cs); - ASSERT_EQ(rmr->committed_size(), 0u); + rtree->uncommit_region(addr, 5 * cs); + ASSERT_EQ(rmr.committed_size(), 0u); // With different stacks { // Commit one region - rmr->add_committed_region(addr, cs, stack); + rtree->commit_region(addr, cs, stack); R r[] = { {addr, cs} }; check(rmr, r); } { // Commit the same region - rmr->add_committed_region(addr, cs, stack2); + rtree->commit_region(addr, cs, stack2); R r[] = { {addr, cs} }; check(rmr, r); } { // Commit a succeeding region - rmr->add_committed_region(addr + cs, cs, stack); + rtree->commit_region(addr + cs, cs, stack); R r[] = { {addr, cs}, {addr + cs, cs} }; check(rmr, r); } { // Commit over two regions - rmr->add_committed_region(addr, 2 * cs, stack); + rtree->commit_region(addr, 2 * cs, stack); R r[] = { {addr, 2 * cs} }; check(rmr, r); } {// Commit first part of a region - rmr->add_committed_region(addr, cs, stack2); + rtree->commit_region(addr, cs, stack2); R r[] = { {addr, cs}, {addr + cs, cs} }; check(rmr, r); } { // Commit second part of a region - rmr->add_committed_region(addr + cs, cs, stack2); + rtree->commit_region(addr + cs, cs, stack2); R r[] = { {addr, 2 * cs} }; check(rmr, r); } { // Commit a third part - rmr->add_committed_region(addr + 2 * cs, cs, stack2); + rtree->commit_region(addr + 2 * cs, cs, stack2); R r[] = { {addr, 3 * cs} }; check(rmr, r); } { // Commit in the middle of a region - rmr->add_committed_region(addr + 1 * cs, cs, stack); + rtree->commit_region(addr + 1 * cs, cs, stack); R r[] = { {addr, cs}, {addr + cs, cs}, {addr + 2 * cs, cs} }; @@ -428,6 +432,8 @@ class VirtualMemoryTrackerTest { } static void test_remove_uncommitted_region() { + RegionsTree* rtree = VirtualMemoryTracker::Instance::tree(); + rtree->tree().remove_all(); size_t size = 0x01000000; ReservedSpace rs = MemoryReserver::reserve(size, mtTest); @@ -442,114 +448,114 @@ class VirtualMemoryTrackerTest { NativeCallStack stack2(&frame2, 1); // Fetch the added RMR for the space - ReservedMemoryRegion* rmr = VirtualMemoryTracker::_reserved_regions->find(ReservedMemoryRegion(addr, size)); + ReservedMemoryRegion rmr = rtree->find_reserved_region(addr); - ASSERT_EQ(rmr->size(), size); - ASSERT_EQ(rmr->base(), addr); + ASSERT_EQ(rmr.size(), size); + ASSERT_EQ(rmr.base(), addr); // Commit Size Granularity const size_t cs = 0x1000; { // Commit regions - rmr->add_committed_region(addr, 3 * cs, stack); + rtree->commit_region(addr, 3 * cs, stack); R r[] = { {addr, 3 * cs} }; check(rmr, r); // Remove only existing - rmr->remove_uncommitted_region(addr, 3 * cs); + rtree->uncommit_region(addr, 3 * cs); check_empty(rmr); } { - rmr->add_committed_region(addr + 0 * cs, cs, stack); - rmr->add_committed_region(addr + 2 * cs, cs, stack); - rmr->add_committed_region(addr + 4 * cs, cs, stack); + rtree->commit_region(addr + 0 * cs, cs, stack); + rtree->commit_region(addr + 2 * cs, cs, stack); + rtree->commit_region(addr + 4 * cs, cs, stack); { // Remove first - rmr->remove_uncommitted_region(addr, cs); + rtree->uncommit_region(addr, cs); R r[] = { {addr + 2 * cs, cs}, {addr + 4 * cs, cs} }; check(rmr, r); } // add back - rmr->add_committed_region(addr, cs, stack); + rtree->commit_region(addr, cs, stack); { // Remove middle - rmr->remove_uncommitted_region(addr + 2 * cs, cs); + rtree->uncommit_region(addr + 2 * cs, cs); R r[] = { {addr + 0 * cs, cs}, {addr + 4 * cs, cs} }; check(rmr, r); } // add back - rmr->add_committed_region(addr + 2 * cs, cs, stack); + rtree->commit_region(addr + 2 * cs, cs, stack); { // Remove end - rmr->remove_uncommitted_region(addr + 4 * cs, cs); + rtree->uncommit_region(addr + 4 * cs, cs); R r[] = { {addr + 0 * cs, cs}, {addr + 2 * cs, cs} }; check(rmr, r); } - rmr->remove_uncommitted_region(addr, 5 * cs); + rtree->uncommit_region(addr, 5 * cs); check_empty(rmr); } { // Remove larger region - rmr->add_committed_region(addr + 1 * cs, cs, stack); - rmr->remove_uncommitted_region(addr, 3 * cs); + rtree->commit_region(addr + 1 * cs, cs, stack); + rtree->uncommit_region(addr, 3 * cs); check_empty(rmr); } { // Remove smaller region - in the middle - rmr->add_committed_region(addr, 3 * cs, stack); - rmr->remove_uncommitted_region(addr + 1 * cs, cs); + rtree->commit_region(addr, 3 * cs, stack); + rtree->uncommit_region(addr + 1 * cs, cs); R r[] = { { addr + 0 * cs, cs}, { addr + 2 * cs, cs} }; check(rmr, r); - rmr->remove_uncommitted_region(addr, 3 * cs); + rtree->uncommit_region(addr, 3 * cs); check_empty(rmr); } { // Remove smaller region - at the beginning - rmr->add_committed_region(addr, 3 * cs, stack); - rmr->remove_uncommitted_region(addr + 0 * cs, cs); + rtree->commit_region(addr, 3 * cs, stack); + rtree->uncommit_region(addr + 0 * cs, cs); R r[] = { { addr + 1 * cs, 2 * cs} }; check(rmr, r); - rmr->remove_uncommitted_region(addr, 3 * cs); + rtree->uncommit_region(addr, 3 * cs); check_empty(rmr); } { // Remove smaller region - at the end - rmr->add_committed_region(addr, 3 * cs, stack); - rmr->remove_uncommitted_region(addr + 2 * cs, cs); + rtree->commit_region(addr, 3 * cs, stack); + rtree->uncommit_region(addr + 2 * cs, cs); R r[] = { { addr, 2 * cs} }; check(rmr, r); - rmr->remove_uncommitted_region(addr, 3 * cs); + rtree->uncommit_region(addr, 3 * cs); check_empty(rmr); } { // Remove smaller, overlapping region - at the beginning - rmr->add_committed_region(addr + 1 * cs, 4 * cs, stack); - rmr->remove_uncommitted_region(addr, 2 * cs); + rtree->commit_region(addr + 1 * cs, 4 * cs, stack); + rtree->uncommit_region(addr, 2 * cs); R r[] = { { addr + 2 * cs, 3 * cs} }; check(rmr, r); - rmr->remove_uncommitted_region(addr + 1 * cs, 4 * cs); + rtree->uncommit_region(addr + 1 * cs, 4 * cs); check_empty(rmr); } { // Remove smaller, overlapping region - at the end - rmr->add_committed_region(addr, 3 * cs, stack); - rmr->remove_uncommitted_region(addr + 2 * cs, 2 * cs); + rtree->commit_region(addr, 3 * cs, stack); + rtree->uncommit_region(addr + 2 * cs, 2 * cs); R r[] = { { addr, 2 * cs} }; check(rmr, r); - rmr->remove_uncommitted_region(addr, 3 * cs); + rtree->uncommit_region(addr, 3 * cs); check_empty(rmr); } } @@ -569,4 +575,4 @@ TEST_VM(NMT_VirtualMemoryTracker, remove_uncommitted_region) { } else { tty->print_cr("skipped."); } -} +} \ No newline at end of file diff --git a/test/hotspot/jtreg/runtime/Thread/TestAlwaysPreTouchStacks.java b/test/hotspot/jtreg/runtime/Thread/TestAlwaysPreTouchStacks.java index 06ddaadf91c..fe4688330e3 100644 --- a/test/hotspot/jtreg/runtime/Thread/TestAlwaysPreTouchStacks.java +++ b/test/hotspot/jtreg/runtime/Thread/TestAlwaysPreTouchStacks.java @@ -169,14 +169,17 @@ public static void main(String[] args) throws Exception { } long expected_delta = numThreads * (max_stack_usage_with_pretouch - min_stack_usage_with_pretouch); long actual_delta = pretouch_committed - no_pretouch_committed; - if (pretouch_committed <= (no_pretouch_committed + expected_delta)) { - throw new RuntimeException("Expected a higher amount of committed with pretouch stacks" + - "PreTouch amount: " + pretouch_committed + - "NoPreTouch amount: " + (no_pretouch_committed + expected_delta)); - } - if (actual_delta < expected_delta) { - throw new RuntimeException("Expected a higher delta between stack committed of with and without pretouch." + - "Expected: " + expected_delta + " Actual: " + actual_delta); + if (((double)pretouch_committed) / ((double)no_pretouch_committed) < 1.20) { + if (pretouch_committed <= (no_pretouch_committed + expected_delta)) { + throw new RuntimeException("Expected a higher amount of committed with pretouch stacks" + + " PreTouch amount: " + pretouch_committed + + " NoPreTouch amount: " + no_pretouch_committed + + " Expected delta: " + expected_delta); + } + if (actual_delta < expected_delta) { + throw new RuntimeException("Expected a higher delta between stack committed of with and without pretouch." + + " Expected: " + expected_delta + " Actual: " + actual_delta); + } } } } From ba32b78bfaf83f69003f83333ab6975b35343fde Mon Sep 17 00:00:00 2001 From: Mikhail Ablakatov Date: Wed, 18 Jun 2025 11:48:45 +0000 Subject: [PATCH 099/213] 8358329: AArch64: emit direct branches in static stubs for small code caches Reviewed-by: aph, eastigeevich --- .../cpu/aarch64/compiledIC_aarch64.cpp | 6 +- .../cpu/aarch64/macroAssembler_aarch64.cpp | 12 +- .../cpu/aarch64/nativeInst_aarch64.cpp | 12 -- .../cpu/aarch64/nativeInst_aarch64.hpp | 5 +- .../c2/aarch64/TestStaticCallStub.java | 144 ++++++++++++++++++ 5 files changed, 160 insertions(+), 19 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/aarch64/TestStaticCallStub.java diff --git a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp index 24a7a78b800..6fe3315014b 100644 --- a/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/compiledIC_aarch64.cpp @@ -90,13 +90,15 @@ void CompiledDirectCall::set_to_interpreted(const methodHandle& callee, address = nativeMovConstReg_at(stub + NativeInstruction::instruction_size); #ifdef ASSERT - NativeGeneralJump* jump = nativeGeneralJump_at(method_holder->next_instruction_address()); + NativeJump* jump = MacroAssembler::codestub_branch_needs_far_jump() + ? nativeGeneralJump_at(method_holder->next_instruction_address()) + : nativeJump_at(method_holder->next_instruction_address()); verify_mt_safe(callee, entry, method_holder, jump); #endif // Update stub. method_holder->set_data((intptr_t)callee()); - NativeGeneralJump::insert_unconditional(method_holder->next_instruction_address(), entry); + MacroAssembler::pd_patch_instruction(method_holder->next_instruction_address(), entry); ICache::invalidate_range(stub, to_interp_stub_size()); // Update jump to call. set_destination_mt_safe(stub); diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 93b303e51c9..cbd941397f3 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -984,11 +984,19 @@ void MacroAssembler::emit_static_call_stub() { mov_metadata(rmethod, nullptr); // Jump to the entry point of the c2i stub. - movptr(rscratch1, 0); - br(rscratch1); + if (codestub_branch_needs_far_jump()) { + movptr(rscratch1, 0); + br(rscratch1); + } else { + b(pc()); + } } int MacroAssembler::static_call_stub_size() { + if (!codestub_branch_needs_far_jump()) { + // isb; movk; movz; movz; b + return 5 * NativeInstruction::instruction_size; + } // isb; movk; movz; movz; movk; movz; movz; br return 8 * NativeInstruction::instruction_size; } diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp index 33158d6b97a..0b05b4ac3e5 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp @@ -386,18 +386,6 @@ void NativeJump::patch_verified_entry(address entry, address verified_entry, add void NativeGeneralJump::verify() { } -void NativeGeneralJump::insert_unconditional(address code_pos, address entry) { - NativeGeneralJump* n_jump = (NativeGeneralJump*)code_pos; - - CodeBuffer cb(code_pos, instruction_size); - MacroAssembler a(&cb); - - a.movptr(rscratch1, (uintptr_t)entry); - a.br(rscratch1); - - ICache::invalidate_range(code_pos, instruction_size); -} - // MT-safe patching of a long jump instruction. void NativeGeneralJump::replace_mt_safe(address instr_addr, address code_buffer) { ShouldNotCallThis(); diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp index 0eb5ff815be..9b9b83e38b8 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, 2108, Red Hat Inc. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -383,7 +383,6 @@ class NativeGeneralJump: public NativeJump { address jump_destination() const; void set_jump_destination(address dest); - static void insert_unconditional(address code_pos, address entry); static void replace_mt_safe(address instr_addr, address code_buffer); static void verify(); }; diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestStaticCallStub.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestStaticCallStub.java new file mode 100644 index 00000000000..0c6535ff856 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestStaticCallStub.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2025, Arm Limited. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package compiler.c2.aarch64; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.*; + +/* + * @test + * @summary Calls to c2i interface stubs should be generated with near branches + * for segmented code cache up to 250MB + * @library /test/lib / + * + * @requires vm.flagless + * @requires os.arch=="aarch64" + * @requires vm.debug == false + * @requires vm.compiler2.enabled + * + * @run driver compiler.c2.aarch64.TestStaticCallStub + */ +public class TestStaticCallStub { + + static String[] nearStaticCallOpcodeSeq = {"isb", "mov", "movk", "movk", "b"}; + static String[] farStaticCallOpcodeSeq = {"isb", "mov", "movk", "movk", "mov", "movk", "movk", "br"}; + + static String extractOpcode(String line) { + line = line.trim(); + int semicolonIndex = line.indexOf(';'); + if (semicolonIndex != -1) { + line = line.substring(0, semicolonIndex).trim(); + } + + String[] words = line.split("\\s+"); + if (words.length > 1) { + return words[1]; + } + + return ""; + } + + static List extractOpcodesN(ListIterator itr, int n) { + List extractedOpcodes = new ArrayList<>(); + + while (itr.hasNext() && extractedOpcodes.size() < n) { + String opcode = extractOpcode(itr.next()); + if (!opcode.isEmpty()) { + extractedOpcodes.add(opcode); + } + } + + return extractedOpcodes; + } + + static void verifyNearStaticCall(ListIterator itr) { + List extractedOpcodes = extractOpcodesN(itr, nearStaticCallOpcodeSeq.length); + + if (!Arrays.asList(nearStaticCallOpcodeSeq).equals(extractedOpcodes)) { + throw new RuntimeException("for code cache < 250MB the static call stub is expected to be implemented using near branch"); + } + + return; + } + + static void verifyFarStaticCall(ListIterator itr) { + List extractedOpcodes = extractOpcodesN(itr, farStaticCallOpcodeSeq.length); + + if (!Arrays.asList(farStaticCallOpcodeSeq).equals(extractedOpcodes)) { + throw new RuntimeException("for code cache > 250MB the static call stub is expected to be implemented using far branch"); + } + + return; + } + + static void runVM(boolean bigCodeCache) throws Exception { + String className = TestStaticCallStub.class.getName(); + String[] procArgs = { + "-XX:-Inline", + "-Xcomp", + "-Xbatch", + "-XX:+TieredCompilation", + "-XX:+SegmentedCodeCache", + "-XX:ReservedCodeCacheSize=" + (bigCodeCache ? "256M" : "200M"), + "-XX:+UnlockDiagnosticVMOptions", + "-XX:CompileCommand=option," + className + "::main,bool,PrintAssembly,true", + className}; + + + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(procArgs); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + List lines = output.asLines(); + + ListIterator itr = lines.listIterator(); + while (itr.hasNext()) { + String line = itr.next(); + if (line.contains("{static_stub}")) { + itr.previous(); + if (bigCodeCache) { + verifyFarStaticCall(itr); + } else { + verifyNearStaticCall(itr); + } + return; + } + } + throw new RuntimeException("Assembly output: static call stub is not found"); + } + + public static void main(String[] args) throws Exception { + if (args.length == 0) { + // Main VM: fork VM with options + runVM(true); + runVM(false); + return; + } + if (args.length > 0) { + // We are in a forked VM. Just exit + System.out.println("Ok"); + } + } +} + From cf78925859dd2640b3c2500fc6be8b5bb308d96e Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Wed, 18 Jun 2025 13:58:45 +0000 Subject: [PATCH 100/213] 8358891: Remove the PerfDataSamplingIntervalFunc code Reviewed-by: shade, jwilhelm --- .../runtime/flags/jvmFlagConstraintsRuntime.cpp | 12 ------------ .../runtime/flags/jvmFlagConstraintsRuntime.hpp | 1 - 2 files changed, 13 deletions(-) diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp index efffa8ac753..f49b7f66690 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp @@ -99,18 +99,6 @@ JVMFlag::Error ContendedPaddingWidthConstraintFunc(int value, bool verbose) { } } -JVMFlag::Error PerfDataSamplingIntervalFunc(int value, bool verbose) { - if ((value % PeriodicTask::interval_gran != 0)) { - JVMFlag::printError(verbose, - "PerfDataSamplingInterval (%d) must be " - "evenly divisible by PeriodicTask::interval_gran (%d)\n", - value, PeriodicTask::interval_gran); - return JVMFlag::VIOLATES_CONSTRAINT; - } else { - return JVMFlag::SUCCESS; - } -} - JVMFlag::Error VMPageSizeConstraintFunc(uintx value, bool verbose) { uintx min = (uintx)os::vm_page_size(); if (value < min) { diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp index 3040dafabc5..ddd2bae1914 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp @@ -39,7 +39,6 @@ f(ccstr, AOTModeConstraintFunc) \ f(int, ObjectAlignmentInBytesConstraintFunc) \ f(int, ContendedPaddingWidthConstraintFunc) \ - f(int, PerfDataSamplingIntervalFunc) \ f(uintx, VMPageSizeConstraintFunc) \ f(size_t, NUMAInterleaveGranularityConstraintFunc) From 42d3604a31c4e5b5391468ee1d2c88c23c54c1d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Wed, 18 Jun 2025 14:07:25 +0000 Subject: [PATCH 101/213] 8359923: Const accessors for the Deferred class Reviewed-by: jsjolen --- src/hotspot/share/utilities/deferred.hpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/hotspot/share/utilities/deferred.hpp b/src/hotspot/share/utilities/deferred.hpp index 8aa095c88e7..a12ca571fe6 100644 --- a/src/hotspot/share/utilities/deferred.hpp +++ b/src/hotspot/share/utilities/deferred.hpp @@ -56,14 +56,27 @@ class Deferred { return &_t; } + const T* get() const { + assert(_initialized, "must be initialized before access"); + return &_t; + } + T& operator*() { return *get(); } + const T& operator*() const { + return *get(); + } + T* operator->() { return get(); } + const T* operator->() const { + return get(); + } + template void initialize(Ts&... args) { assert(!_initialized, "Double initialization forbidden"); From 984d7f9cdfb0d75ea906ce32df0b6c447f4d5954 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Wed, 18 Jun 2025 14:43:55 +0000 Subject: [PATCH 102/213] 8359895: JFR: method-timing view doesn't work Reviewed-by: mgronlun --- src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini index 018f41bbf22..fd9636f17ab 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/view.ini @@ -471,8 +471,8 @@ table = "COLUMN 'Alloc. Time', 'Application Method', 'Object Age', 'Heap Usage' [application.method-timing] label = "Method Timing" -table = "COLUMN 'Timed Method', 'Invocations', 'Min. Tim', 'Max. Time', 'Average Time' - FORMAT none, none, ms-precision:6 +table = "COLUMN 'Timed Method', 'Invocations', 'Min. Time', 'Max. Time', 'Average Time' + FORMAT none, none, ms-precision:6, ms-precision:6, ms-precision:6 SELECT LAST_BATCH(method) AS M, LAST_BATCH(invocations), LAST_BATCH(minimum), LAST_BATCH(maximum), LAST_BATCH(average) FROM jdk.MethodTiming GROUP BY method ORDER BY average" From b7fcd0b2351cee8d3d18abaf0bf5905d20c9d46c Mon Sep 17 00:00:00 2001 From: Manukumar V S Date: Wed, 18 Jun 2025 16:41:31 +0000 Subject: [PATCH 103/213] 8359889: java/awt/MenuItem/SetLabelTest.java inadvertently triggers clicks on items pinned to the taskbar Reviewed-by: aivanov, kizune --- test/jdk/java/awt/MenuItem/SetLabelTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/java/awt/MenuItem/SetLabelTest.java b/test/jdk/java/awt/MenuItem/SetLabelTest.java index f8a506ed7e4..154fb0d4987 100644 --- a/test/jdk/java/awt/MenuItem/SetLabelTest.java +++ b/test/jdk/java/awt/MenuItem/SetLabelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,7 +120,7 @@ private void showPopup(MouseEvent e) { }); frame.setMenuBar(mb); frame.setSize(300, 200); - frame.setLocation(500,500); + frame.setLocationRelativeTo(null); frame.setVisible(true); } From 7bc0d82450e210b14c9f89687582d78a0a50ee54 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 18 Jun 2025 18:05:18 +0000 Subject: [PATCH 104/213] 8359227: Code cache/heap size options should be size_t Reviewed-by: mhaessig, tschatzl --- .../cpu/aarch64/c1_globals_aarch64.hpp | 18 ++++++------- .../cpu/aarch64/c2_globals_aarch64.hpp | 18 ++++++------- src/hotspot/cpu/aarch64/globals_aarch64.hpp | 2 +- src/hotspot/cpu/arm/c1_globals_arm.hpp | 4 +-- src/hotspot/cpu/arm/c2_globals_arm.hpp | 4 +-- src/hotspot/cpu/arm/globals_arm.hpp | 8 +++--- src/hotspot/cpu/ppc/c1_globals_ppc.hpp | 18 ++++++------- src/hotspot/cpu/ppc/c2_globals_ppc.hpp | 18 ++++++------- src/hotspot/cpu/ppc/globals_ppc.hpp | 10 +++---- src/hotspot/cpu/riscv/c1_globals_riscv.hpp | 18 ++++++------- src/hotspot/cpu/riscv/c2_globals_riscv.hpp | 18 ++++++------- src/hotspot/cpu/riscv/globals_riscv.hpp | 4 +-- src/hotspot/cpu/s390/c1_globals_s390.hpp | 18 ++++++------- src/hotspot/cpu/s390/c2_globals_s390.hpp | 18 ++++++------- src/hotspot/cpu/s390/globals_s390.hpp | 4 +-- src/hotspot/cpu/x86/c1_globals_x86.hpp | 18 ++++++------- src/hotspot/cpu/x86/c2_globals_x86.hpp | 22 ++++++++-------- src/hotspot/cpu/x86/globals_x86.hpp | 4 +-- src/hotspot/cpu/zero/globals_zero.hpp | 10 +++---- src/hotspot/share/code/codeCache.cpp | 6 ++--- .../share/compiler/compilationPolicy.cpp | 6 ++--- .../share/compiler/compilerDefinitions.cpp | 12 ++++----- .../share/compiler/compiler_globals_pd.hpp | 18 ++++++------- .../share/jvmci/jvmciCompilerToVMInit.cpp | 17 ++++++------ src/hotspot/share/memory/heap.cpp | 2 +- src/hotspot/share/runtime/arguments.cpp | 2 +- .../flags/jvmFlagConstraintsCompiler.cpp | 8 +++--- .../flags/jvmFlagConstraintsCompiler.hpp | 4 +-- .../flags/jvmFlagConstraintsRuntime.cpp | 4 +-- .../flags/jvmFlagConstraintsRuntime.hpp | 4 +-- src/hotspot/share/runtime/globals.hpp | 26 +++++++++---------- .../codecache/CheckSegmentedCodeCache.java | 2 +- .../codecache/jmx/CodeCacheUtils.java | 6 ++--- .../stress/RandomAllocationTest.java | 4 +-- .../stress/ReturnBlobToWrongHeapTest.java | 6 ++--- .../whitebox/AllocationCodeBlobTest.java | 4 +-- .../event/compiler/TestCodeCacheConfig.java | 2 +- .../jfr/event/compiler/TestCodeSweeper.java | 4 +-- .../jdk/test/whitebox/vm_flags/UintxTest.java | 4 +-- test/lib/jdk/test/whitebox/code/BlobType.java | 4 +-- 40 files changed, 190 insertions(+), 189 deletions(-) diff --git a/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp b/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp index c2d1405b005..a8a2fa8b2ee 100644 --- a/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c1_globals_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -43,15 +43,15 @@ define_pd_global(intx, CompileThreshold, 1500 ); define_pd_global(intx, OnStackReplacePercentage, 933 ); define_pd_global(intx, NewSizeThreadIncrease, 4*K ); -define_pd_global(intx, InitialCodeCacheSize, 160*K); -define_pd_global(intx, ReservedCodeCacheSize, 32*M ); -define_pd_global(intx, NonProfiledCodeHeapSize, 13*M ); -define_pd_global(intx, ProfiledCodeHeapSize, 14*M ); -define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(size_t, InitialCodeCacheSize, 160*K); +define_pd_global(size_t, ReservedCodeCacheSize, 32*M ); +define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M ); +define_pd_global(size_t, ProfiledCodeHeapSize, 14*M ); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M ); define_pd_global(bool, ProfileInterpreter, false); -define_pd_global(intx, CodeCacheExpansionSize, 32*K ); -define_pd_global(uintx, CodeCacheMinBlockLength, 1); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, CodeCacheExpansionSize, 32*K ); +define_pd_global(size_t, CodeCacheMinBlockLength, 1); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, NeverActAsServerClassMachine, true ); define_pd_global(uint64_t,MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); diff --git a/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp index 6c5c469ca27..94a80dec3ea 100644 --- a/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_globals_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -51,8 +51,8 @@ define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, LoopUnrollLimit, 60); define_pd_global(intx, LoopPercentProfileLimit, 10); // InitialCodeCacheSize derived from specjbb2000 run. -define_pd_global(intx, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(intx, CodeCacheExpansionSize, 64*K); +define_pd_global(size_t, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(size_t, CodeCacheExpansionSize, 64*K); // Ergonomics related flags define_pd_global(uint64_t,MaxRAM, 128ULL*G); @@ -69,12 +69,12 @@ define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 8); define_pd_global(bool, IdealizeClearArrayNode, true); -define_pd_global(intx, ReservedCodeCacheSize, 48*M); -define_pd_global(intx, NonProfiledCodeHeapSize, 21*M); -define_pd_global(intx, ProfiledCodeHeapSize, 22*M); -define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); -define_pd_global(uintx, CodeCacheMinBlockLength, 6); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, ReservedCodeCacheSize, 48*M); +define_pd_global(size_t, NonProfiledCodeHeapSize, 21*M); +define_pd_global(size_t, ProfiledCodeHeapSize, 22*M); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(size_t, CodeCacheMinBlockLength, 6); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); // Ergonomics related flags define_pd_global(bool, NeverActAsServerClassMachine, false); diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index b316103d656..d195af8cef4 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -38,7 +38,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap nulls define_pd_global(bool, DelayCompilerStubsGeneration, COMPILER2_OR_JVMCI); -define_pd_global(uintx, CodeCacheSegmentSize, 64); +define_pd_global(size_t, CodeCacheSegmentSize, 64); define_pd_global(intx, CodeEntryAlignment, 64); define_pd_global(intx, OptoLoopAlignment, 16); diff --git a/src/hotspot/cpu/arm/c1_globals_arm.hpp b/src/hotspot/cpu/arm/c1_globals_arm.hpp index d22d39d6369..396f206975b 100644 --- a/src/hotspot/cpu/arm/c1_globals_arm.hpp +++ b/src/hotspot/cpu/arm/c1_globals_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ define_pd_global(size_t, ProfiledCodeHeapSize, 14*M ); define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M ); define_pd_global(bool, ProfileInterpreter, false); define_pd_global(size_t, CodeCacheExpansionSize, 32*K ); -define_pd_global(uintx, CodeCacheMinBlockLength, 1); +define_pd_global(size_t, CodeCacheMinBlockLength, 1); define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, NeverActAsServerClassMachine, true); define_pd_global(uint64_t, MaxRAM, 1ULL*G); diff --git a/src/hotspot/cpu/arm/c2_globals_arm.hpp b/src/hotspot/cpu/arm/c2_globals_arm.hpp index abd3ef6aef5..d739e67360a 100644 --- a/src/hotspot/cpu/arm/c2_globals_arm.hpp +++ b/src/hotspot/cpu/arm/c2_globals_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,7 +94,7 @@ define_pd_global(size_t, CodeCacheExpansionSize, 32*K); // Ergonomics related flags define_pd_global(uint64_t, MaxRAM, 4ULL*G); #endif -define_pd_global(uintx, CodeCacheMinBlockLength, 6); +define_pd_global(size_t, CodeCacheMinBlockLength, 6); define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, TrapBasedRangeChecks, false); // Not needed diff --git a/src/hotspot/cpu/arm/globals_arm.hpp b/src/hotspot/cpu/arm/globals_arm.hpp index 9c4b8500e18..363a9a2c25c 100644 --- a/src/hotspot/cpu/arm/globals_arm.hpp +++ b/src/hotspot/cpu/arm/globals_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,9 +36,9 @@ define_pd_global(bool, TrapBasedNullChecks, false); // Not needed define_pd_global(bool, DelayCompilerStubsGeneration, false); // No need - only few compiler's stubs -define_pd_global(uintx, CodeCacheSegmentSize, 64); -define_pd_global(intx, CodeEntryAlignment, 16); -define_pd_global(intx, OptoLoopAlignment, 16); +define_pd_global(size_t, CodeCacheSegmentSize, 64); +define_pd_global(intx, CodeEntryAlignment, 16); +define_pd_global(intx, OptoLoopAlignment, 16); #define DEFAULT_STACK_YELLOW_PAGES (2) #define DEFAULT_STACK_RED_PAGES (1) diff --git a/src/hotspot/cpu/ppc/c1_globals_ppc.hpp b/src/hotspot/cpu/ppc/c1_globals_ppc.hpp index 23604b5c083..ab014287250 100644 --- a/src/hotspot/cpu/ppc/c1_globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/c1_globals_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -44,17 +44,17 @@ define_pd_global(intx, CompileThreshold, 1000); define_pd_global(intx, OnStackReplacePercentage, 1400); define_pd_global(bool, ProfileInterpreter, false); -define_pd_global(uintx, ReservedCodeCacheSize, 32*M); -define_pd_global(uintx, NonProfiledCodeHeapSize, 13*M ); -define_pd_global(uintx, ProfiledCodeHeapSize, 14*M ); -define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M ); -define_pd_global(uintx, CodeCacheExpansionSize, 32*K); -define_pd_global(uintx, CodeCacheMinBlockLength, 1); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, ReservedCodeCacheSize, 32*M); +define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M ); +define_pd_global(size_t, ProfiledCodeHeapSize, 14*M ); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(size_t, CodeCacheExpansionSize, 32*K); +define_pd_global(size_t, CodeCacheMinBlockLength, 1); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, NeverActAsServerClassMachine, true); define_pd_global(size_t, NewSizeThreadIncrease, 16*K); define_pd_global(uint64_t, MaxRAM, 1ULL*G); -define_pd_global(uintx, InitialCodeCacheSize, 160*K); +define_pd_global(size_t, InitialCodeCacheSize, 160*K); #endif // !COMPILER2 define_pd_global(bool, UseTypeProfile, false); diff --git a/src/hotspot/cpu/ppc/c2_globals_ppc.hpp b/src/hotspot/cpu/ppc/c2_globals_ppc.hpp index 3e83ac4f3a4..706255d035a 100644 --- a/src/hotspot/cpu/ppc/c2_globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/c2_globals_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2019 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -78,17 +78,17 @@ define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 16); define_pd_global(bool, OptoScheduling, false); define_pd_global(bool, IdealizeClearArrayNode, true); -define_pd_global(uintx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(uintx, ReservedCodeCacheSize, 48*M); -define_pd_global(uintx, NonProfiledCodeHeapSize, 21*M); -define_pd_global(uintx, ProfiledCodeHeapSize, 22*M); -define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M ); -define_pd_global(uintx, CodeCacheExpansionSize, 64*K); +define_pd_global(size_t, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(size_t, ReservedCodeCacheSize, 48*M); +define_pd_global(size_t, NonProfiledCodeHeapSize, 21*M); +define_pd_global(size_t, ProfiledCodeHeapSize, 22*M); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(size_t, CodeCacheExpansionSize, 64*K); // Ergonomics related flags define_pd_global(uint64_t, MaxRAM, 128ULL*G); -define_pd_global(uintx, CodeCacheMinBlockLength, 6); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, CodeCacheMinBlockLength, 6); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, TrapBasedRangeChecks, true); diff --git a/src/hotspot/cpu/ppc/globals_ppc.hpp b/src/hotspot/cpu/ppc/globals_ppc.hpp index f944408fe29..65334bf0389 100644 --- a/src/hotspot/cpu/ppc/globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/globals_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -59,10 +59,10 @@ define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES); define_pd_global(bool, VMContinuations, true); // Use large code-entry alignment. -define_pd_global(uintx, CodeCacheSegmentSize, 128); -define_pd_global(intx, CodeEntryAlignment, 64); -define_pd_global(intx, OptoLoopAlignment, 16); -define_pd_global(intx, InlineSmallCode, 1500); +define_pd_global(size_t, CodeCacheSegmentSize, 128); +define_pd_global(intx, CodeEntryAlignment, 64); +define_pd_global(intx, OptoLoopAlignment, 16); +define_pd_global(intx, InlineSmallCode, 1500); // Flags for template interpreter. define_pd_global(bool, RewriteBytecodes, true); diff --git a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp index 311405dbc2b..d64b3b66fa2 100644 --- a/src/hotspot/cpu/riscv/c1_globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/c1_globals_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -43,15 +43,15 @@ define_pd_global(intx, CompileThreshold, 1500 ); define_pd_global(intx, OnStackReplacePercentage, 933 ); define_pd_global(intx, NewSizeThreadIncrease, 4*K ); -define_pd_global(intx, InitialCodeCacheSize, 160*K); -define_pd_global(intx, ReservedCodeCacheSize, 32*M ); -define_pd_global(intx, NonProfiledCodeHeapSize, 13*M ); -define_pd_global(intx, ProfiledCodeHeapSize, 14*M ); -define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(size_t, InitialCodeCacheSize, 160*K); +define_pd_global(size_t, ReservedCodeCacheSize, 32*M ); +define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M ); +define_pd_global(size_t, ProfiledCodeHeapSize, 14*M ); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M ); define_pd_global(bool, ProfileInterpreter, false); -define_pd_global(intx, CodeCacheExpansionSize, 32*K ); -define_pd_global(uintx, CodeCacheMinBlockLength, 1); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, CodeCacheExpansionSize, 32*K ); +define_pd_global(size_t, CodeCacheMinBlockLength, 1); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, NeverActAsServerClassMachine, true ); define_pd_global(uint64_t, MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); diff --git a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp index 79bdc4917c9..372865fc291 100644 --- a/src/hotspot/cpu/riscv/c2_globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/c2_globals_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -51,8 +51,8 @@ define_pd_global(intx, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, LoopUnrollLimit, 60); define_pd_global(intx, LoopPercentProfileLimit, 10); // InitialCodeCacheSize derived from specjbb2000 run. -define_pd_global(intx, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(intx, CodeCacheExpansionSize, 64*K); +define_pd_global(size_t, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(size_t, CodeCacheExpansionSize, 64*K); // Ergonomics related flags define_pd_global(uint64_t,MaxRAM, 128ULL*G); @@ -69,12 +69,12 @@ define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 16); define_pd_global(bool, IdealizeClearArrayNode, true); -define_pd_global(intx, ReservedCodeCacheSize, 48*M); -define_pd_global(intx, NonProfiledCodeHeapSize, 21*M); -define_pd_global(intx, ProfiledCodeHeapSize, 22*M); -define_pd_global(intx, NonNMethodCodeHeapSize, 5*M ); -define_pd_global(uintx, CodeCacheMinBlockLength, 6); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, ReservedCodeCacheSize, 48*M); +define_pd_global(size_t, NonProfiledCodeHeapSize, 21*M); +define_pd_global(size_t, ProfiledCodeHeapSize, 22*M); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(size_t, CodeCacheMinBlockLength, 6); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); // Ergonomics related flags define_pd_global(bool, NeverActAsServerClassMachine, false); diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index d67e05bbb6d..c78bfaa8ffd 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -38,7 +38,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap nulls define_pd_global(bool, DelayCompilerStubsGeneration, COMPILER2_OR_JVMCI); -define_pd_global(uintx, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment. +define_pd_global(size_t, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment. define_pd_global(intx, CodeEntryAlignment, 64); define_pd_global(intx, OptoLoopAlignment, 16); diff --git a/src/hotspot/cpu/s390/c1_globals_s390.hpp b/src/hotspot/cpu/s390/c1_globals_s390.hpp index 130a53ad084..1b2b698a737 100644 --- a/src/hotspot/cpu/s390/c1_globals_s390.hpp +++ b/src/hotspot/cpu/s390/c1_globals_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -44,17 +44,17 @@ define_pd_global(intx, CompileThreshold, 1000); define_pd_global(intx, OnStackReplacePercentage, 1400); define_pd_global(bool, ProfileInterpreter, false); -define_pd_global(uintx, ReservedCodeCacheSize, 32*M); -define_pd_global(uintx, NonProfiledCodeHeapSize, 13*M); -define_pd_global(uintx, ProfiledCodeHeapSize, 14*M); -define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M); -define_pd_global(uintx, CodeCacheExpansionSize, 32*K); -define_pd_global(uintx, CodeCacheMinBlockLength, 1); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, ReservedCodeCacheSize, 32*M); +define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M); +define_pd_global(size_t, ProfiledCodeHeapSize, 14*M); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M); +define_pd_global(size_t, CodeCacheExpansionSize, 32*K); +define_pd_global(size_t, CodeCacheMinBlockLength, 1); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, NeverActAsServerClassMachine, true); define_pd_global(size_t, NewSizeThreadIncrease, 16*K); define_pd_global(uint64_t, MaxRAM, 1ULL*G); -define_pd_global(uintx, InitialCodeCacheSize, 160*K); +define_pd_global(size_t, InitialCodeCacheSize, 160*K); #endif // !COMPILER2 define_pd_global(bool, UseTypeProfile, false); diff --git a/src/hotspot/cpu/s390/c2_globals_s390.hpp b/src/hotspot/cpu/s390/c2_globals_s390.hpp index b8b45cbc80e..94190c25f5b 100644 --- a/src/hotspot/cpu/s390/c2_globals_s390.hpp +++ b/src/hotspot/cpu/s390/c2_globals_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -67,17 +67,17 @@ define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 16); define_pd_global(bool, IdealizeClearArrayNode, false); // InitialCodeCacheSize derived from specjbb2000 run. -define_pd_global(uintx, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(uintx, ReservedCodeCacheSize, 48*M); -define_pd_global(uintx, NonProfiledCodeHeapSize, 21*M); -define_pd_global(uintx, ProfiledCodeHeapSize, 22*M); -define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M); -define_pd_global(uintx, CodeCacheExpansionSize, 64*K); +define_pd_global(size_t, InitialCodeCacheSize, 2048*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(size_t, ReservedCodeCacheSize, 48*M); +define_pd_global(size_t, NonProfiledCodeHeapSize, 21*M); +define_pd_global(size_t, ProfiledCodeHeapSize, 22*M); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M); +define_pd_global(size_t, CodeCacheExpansionSize, 64*K); // Ergonomics related flags define_pd_global(uint64_t, MaxRAM, 128ULL*G); -define_pd_global(uintx, CodeCacheMinBlockLength, 4); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, CodeCacheMinBlockLength, 4); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, TrapBasedRangeChecks, false); // Not needed on z/Architecture. diff --git a/src/hotspot/cpu/s390/globals_s390.hpp b/src/hotspot/cpu/s390/globals_s390.hpp index cf4be20397c..07987ea3469 100644 --- a/src/hotspot/cpu/s390/globals_s390.hpp +++ b/src/hotspot/cpu/s390/globals_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2018 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -38,7 +38,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap nu define_pd_global(bool, DelayCompilerStubsGeneration, COMPILER2_OR_JVMCI); -define_pd_global(uintx, CodeCacheSegmentSize, 256); +define_pd_global(size_t, CodeCacheSegmentSize, 256); // This shall be at least 32 for proper branch target alignment. // Ideally, this is 256 (cache line size). This keeps code end data // on separate lines. But we reduced it to 64 since 256 increased diff --git a/src/hotspot/cpu/x86/c1_globals_x86.hpp b/src/hotspot/cpu/x86/c1_globals_x86.hpp index b2085a0b4b3..be5c443a695 100644 --- a/src/hotspot/cpu/x86/c1_globals_x86.hpp +++ b/src/hotspot/cpu/x86/c1_globals_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,15 +42,15 @@ define_pd_global(intx, CompileThreshold, 1500 ); define_pd_global(intx, OnStackReplacePercentage, 933 ); define_pd_global(size_t, NewSizeThreadIncrease, 4*K ); -define_pd_global(uintx, InitialCodeCacheSize, 160*K); -define_pd_global(uintx, ReservedCodeCacheSize, 32*M ); -define_pd_global(uintx, NonProfiledCodeHeapSize, 13*M ); -define_pd_global(uintx, ProfiledCodeHeapSize, 14*M ); -define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(size_t, InitialCodeCacheSize, 160*K); +define_pd_global(size_t, ReservedCodeCacheSize, 32*M ); +define_pd_global(size_t, NonProfiledCodeHeapSize, 13*M ); +define_pd_global(size_t, ProfiledCodeHeapSize, 14*M ); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M ); define_pd_global(bool, ProfileInterpreter, false); -define_pd_global(uintx, CodeCacheExpansionSize, 32*K ); -define_pd_global(uintx, CodeCacheMinBlockLength, 1 ); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, CodeCacheExpansionSize, 32*K ); +define_pd_global(size_t, CodeCacheMinBlockLength, 1 ); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, NeverActAsServerClassMachine, true ); define_pd_global(uint64_t, MaxRAM, 1ULL*G); define_pd_global(bool, CICompileOSR, true ); diff --git a/src/hotspot/cpu/x86/c2_globals_x86.hpp b/src/hotspot/cpu/x86/c2_globals_x86.hpp index 64dda0a8947..a25f5da5e56 100644 --- a/src/hotspot/cpu/x86/c2_globals_x86.hpp +++ b/src/hotspot/cpu/x86/c2_globals_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,8 +50,8 @@ define_pd_global(intx, InteriorEntryAlignment, 16); define_pd_global(size_t, NewSizeThreadIncrease, ScaleForWordSize(4*K)); define_pd_global(intx, LoopUnrollLimit, 60); // InitialCodeCacheSize derived from specjbb2000 run. -define_pd_global(uintx, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(uintx, CodeCacheExpansionSize, 64*K); +define_pd_global(size_t, InitialCodeCacheSize, 2496*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(size_t, CodeCacheExpansionSize, 64*K); // Ergonomics related flags define_pd_global(uint64_t, MaxRAM, 128ULL*G); @@ -60,8 +60,8 @@ define_pd_global(intx, InteriorEntryAlignment, 4); define_pd_global(size_t, NewSizeThreadIncrease, 4*K); define_pd_global(intx, LoopUnrollLimit, 50); // Design center runs on 1.3.1 // InitialCodeCacheSize derived from specjbb2000 run. -define_pd_global(uintx, InitialCodeCacheSize, 2304*K); // Integral multiple of CodeCacheExpansionSize -define_pd_global(uintx, CodeCacheExpansionSize, 32*K); +define_pd_global(size_t, InitialCodeCacheSize, 2304*K); // Integral multiple of CodeCacheExpansionSize +define_pd_global(size_t, CodeCacheExpansionSize, 32*K); // Ergonomics related flags define_pd_global(uint64_t, MaxRAM, 4ULL*G); @@ -79,12 +79,12 @@ define_pd_global(bool, SuperWordLoopUnrollAnalysis, true); define_pd_global(uint, SuperWordStoreToLoadForwardingFailureDetection, 16); define_pd_global(bool, IdealizeClearArrayNode, true); -define_pd_global(uintx, ReservedCodeCacheSize, 48*M); -define_pd_global(uintx, NonProfiledCodeHeapSize, 21*M); -define_pd_global(uintx, ProfiledCodeHeapSize, 22*M); -define_pd_global(uintx, NonNMethodCodeHeapSize, 5*M ); -define_pd_global(uintx, CodeCacheMinBlockLength, 6); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 400*K); +define_pd_global(size_t, ReservedCodeCacheSize, 48*M); +define_pd_global(size_t, NonProfiledCodeHeapSize, 21*M); +define_pd_global(size_t, ProfiledCodeHeapSize, 22*M); +define_pd_global(size_t, NonNMethodCodeHeapSize, 5*M ); +define_pd_global(size_t, CodeCacheMinBlockLength, 6); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 400*K); define_pd_global(bool, TrapBasedRangeChecks, false); // Not needed on x86. diff --git a/src/hotspot/cpu/x86/globals_x86.hpp b/src/hotspot/cpu/x86/globals_x86.hpp index a1d4a71874f..103e22d0185 100644 --- a/src/hotspot/cpu/x86/globals_x86.hpp +++ b/src/hotspot/cpu/x86/globals_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ define_pd_global(bool, UncommonNullCast, true); // Uncommon-trap nulls define_pd_global(bool, DelayCompilerStubsGeneration, COMPILER2_OR_JVMCI); -define_pd_global(uintx, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment. +define_pd_global(size_t, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment. // See 4827828 for this change. There is no globals_core_i486.hpp. I can't // assign a different value for C2 without touching a number of files. Use // #ifdef to minimize the change as it's late in Mantis. -- FIXME. diff --git a/src/hotspot/cpu/zero/globals_zero.hpp b/src/hotspot/cpu/zero/globals_zero.hpp index 76f9692e202..6b6c6ea983c 100644 --- a/src/hotspot/cpu/zero/globals_zero.hpp +++ b/src/hotspot/cpu/zero/globals_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010, 2011 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -38,10 +38,10 @@ define_pd_global(bool, UncommonNullCast, true); define_pd_global(bool, DelayCompilerStubsGeneration, false); // Don't have compiler's stubs -define_pd_global(uintx, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment. -define_pd_global(intx, CodeEntryAlignment, 32); -define_pd_global(intx, OptoLoopAlignment, 16); -define_pd_global(intx, InlineSmallCode, 1000); +define_pd_global(size_t, CodeCacheSegmentSize, 64 COMPILER1_AND_COMPILER2_PRESENT(+64)); // Tiered compilation has large code-entry alignment. +define_pd_global(intx, CodeEntryAlignment, 32); +define_pd_global(intx, OptoLoopAlignment, 16); +define_pd_global(intx, InlineSmallCode, 1000); // not used, but must satisfy following constraints: // 1.) must be in the allowed range for intx *and* diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 3a5da1d7cd2..9d505df8b72 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -433,7 +433,7 @@ void CodeCache::add_heap(ReservedSpace rs, const char* name, CodeBlobType code_b add_heap(heap); // Reserve Space - size_t size_initial = MIN2((size_t)InitialCodeCacheSize, rs.size()); + size_t size_initial = MIN2(InitialCodeCacheSize, rs.size()); size_initial = align_up(size_initial, rs.page_size()); if (!heap->reserve(rs, size_initial, CodeCacheSegmentSize)) { vm_exit_during_initialization(err_msg("Could not reserve enough space in %s (%zuK)", @@ -1106,9 +1106,9 @@ size_t CodeCache::freelists_length() { void icache_init(); void CodeCache::initialize() { - assert(CodeCacheSegmentSize >= (uintx)CodeEntryAlignment, "CodeCacheSegmentSize must be large enough to align entry points"); + assert(CodeCacheSegmentSize >= (size_t)CodeEntryAlignment, "CodeCacheSegmentSize must be large enough to align entry points"); #ifdef COMPILER2 - assert(CodeCacheSegmentSize >= (uintx)OptoLoopAlignment, "CodeCacheSegmentSize must be large enough to align inner loops"); + assert(CodeCacheSegmentSize >= (size_t)OptoLoopAlignment, "CodeCacheSegmentSize must be large enough to align inner loops"); #endif assert(CodeCacheSegmentSize >= sizeof(jdouble), "CodeCacheSegmentSize must be large enough to align constants"); // This was originally just a check of the alignment, causing failure, instead, round diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index bab437eaade..5ca719d0309 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -572,10 +572,10 @@ void CompilationPolicy::initialize() { c2_size = C2Compiler::initial_code_buffer_size(); #endif size_t buffer_size = c1_only ? c1_size : (c1_size/3 + 2*c2_size/3); - int max_count = (ReservedCodeCacheSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / (int)buffer_size; - if (count > max_count) { + size_t max_count = (ReservedCodeCacheSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / buffer_size; + if ((size_t)count > max_count) { // Lower the compiler count such that all buffers fit into the code cache - count = MAX2(max_count, min_count); + count = MAX2((int)max_count, min_count); } FLAG_SET_ERGO(CICompilerCount, count); } diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp index f82e96be6ae..fa894559fef 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.cpp +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp @@ -313,7 +313,7 @@ void CompilerConfig::set_compilation_policy_flags() { // Increase the code cache size - tiered compiles a lot more. if (FLAG_IS_DEFAULT(ReservedCodeCacheSize)) { FLAG_SET_ERGO(ReservedCodeCacheSize, - MIN2(CODE_CACHE_DEFAULT_LIMIT, (size_t)ReservedCodeCacheSize * 5)); + MIN2(CODE_CACHE_DEFAULT_LIMIT, ReservedCodeCacheSize * 5)); } // Enable SegmentedCodeCache if tiered compilation is enabled, ReservedCodeCacheSize >= 240M // and the code cache contains at least 8 pages (segmentation disables advantage of huge pages). @@ -475,26 +475,26 @@ void CompilerConfig::set_jvmci_specific_flags() { bool CompilerConfig::check_args_consistency(bool status) { // Check lower bounds of the code cache // Template Interpreter code is approximately 3X larger in debug builds. - uint min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3); + size_t min_code_cache_size = CodeCacheMinimumUseSpace DEBUG_ONLY(* 3); if (ReservedCodeCacheSize < InitialCodeCacheSize) { jio_fprintf(defaultStream::error_stream(), - "Invalid ReservedCodeCacheSize: %dK. Must be at least InitialCodeCacheSize=%dK.\n", + "Invalid ReservedCodeCacheSize: %zuK. Must be at least InitialCodeCacheSize=%zuK.\n", ReservedCodeCacheSize/K, InitialCodeCacheSize/K); status = false; } else if (ReservedCodeCacheSize < min_code_cache_size) { jio_fprintf(defaultStream::error_stream(), - "Invalid ReservedCodeCacheSize=%dK. Must be at least %uK.\n", ReservedCodeCacheSize/K, + "Invalid ReservedCodeCacheSize=%zuK. Must be at least %zuK.\n", ReservedCodeCacheSize/K, min_code_cache_size/K); status = false; } else if (ReservedCodeCacheSize > CODE_CACHE_SIZE_LIMIT) { // Code cache size larger than CODE_CACHE_SIZE_LIMIT is not supported. jio_fprintf(defaultStream::error_stream(), - "Invalid ReservedCodeCacheSize=%dM. Must be at most %uM.\n", ReservedCodeCacheSize/M, + "Invalid ReservedCodeCacheSize=%zuM. Must be at most %zuM.\n", ReservedCodeCacheSize/M, CODE_CACHE_SIZE_LIMIT/M); status = false; } else if (NonNMethodCodeHeapSize < min_code_cache_size) { jio_fprintf(defaultStream::error_stream(), - "Invalid NonNMethodCodeHeapSize=%dK. Must be at least %uK.\n", NonNMethodCodeHeapSize/K, + "Invalid NonNMethodCodeHeapSize=%zuK. Must be at least %zuK.\n", NonNMethodCodeHeapSize/K, min_code_cache_size/K); status = false; } diff --git a/src/hotspot/share/compiler/compiler_globals_pd.hpp b/src/hotspot/share/compiler/compiler_globals_pd.hpp index f27033c0607..90edd952c77 100644 --- a/src/hotspot/share/compiler/compiler_globals_pd.hpp +++ b/src/hotspot/share/compiler/compiler_globals_pd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,15 +61,15 @@ define_pd_global(intx, OnStackReplacePercentage, 0); define_pd_global(size_t, NewSizeThreadIncrease, 4*K); define_pd_global(bool, InlineClassNatives, true); define_pd_global(bool, InlineUnsafeOps, true); -define_pd_global(uintx, InitialCodeCacheSize, 160*K); -define_pd_global(uintx, ReservedCodeCacheSize, 32*M); -define_pd_global(uintx, NonProfiledCodeHeapSize, 0); -define_pd_global(uintx, ProfiledCodeHeapSize, 0); -define_pd_global(uintx, NonNMethodCodeHeapSize, 32*M); +define_pd_global(size_t, InitialCodeCacheSize, 160*K); +define_pd_global(size_t, ReservedCodeCacheSize, 32*M); +define_pd_global(size_t, NonProfiledCodeHeapSize, 0); +define_pd_global(size_t, ProfiledCodeHeapSize, 0); +define_pd_global(size_t, NonNMethodCodeHeapSize, 32*M); -define_pd_global(uintx, CodeCacheExpansionSize, 32*K); -define_pd_global(uintx, CodeCacheMinBlockLength, 1); -define_pd_global(uintx, CodeCacheMinimumUseSpace, 200*K); +define_pd_global(size_t, CodeCacheExpansionSize, 32*K); +define_pd_global(size_t, CodeCacheMinBlockLength, 1); +define_pd_global(size_t, CodeCacheMinimumUseSpace, 200*K); #ifndef ZERO define_pd_global(bool, NeverActAsServerClassMachine, true); define_pd_global(uint64_t,MaxRAM, 1ULL*G); diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp index 1beb1917b9a..b6d919fdfe9 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp @@ -343,7 +343,7 @@ JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) { return vmIntrinsics; } -#define PREDEFINED_CONFIG_FLAGS(do_bool_flag, do_int_flag, do_intx_flag, do_uintx_flag) \ +#define PREDEFINED_CONFIG_FLAGS(do_bool_flag, do_int_flag, do_size_t_flag, do_intx_flag, do_uintx_flag) \ do_int_flag(AllocateInstancePrefetchLines) \ do_int_flag(AllocatePrefetchDistance) \ do_intx_flag(AllocatePrefetchInstr) \ @@ -354,7 +354,7 @@ JVMCIObjectArray CompilerToVM::initialize_intrinsics(JVMCI_TRAPS) { do_bool_flag(BootstrapJVMCI) \ do_bool_flag(CITime) \ do_bool_flag(CITimeEach) \ - do_uintx_flag(CodeCacheSegmentSize) \ + do_size_t_flag(CodeCacheSegmentSize) \ do_intx_flag(CodeEntryAlignment) \ do_int_flag(ContendedPaddingWidth) \ do_bool_flag(DontCompileHugeMethods) \ @@ -541,16 +541,17 @@ jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS) { JVMCIObject vmFlagObj = JVMCIENV->new_VMFlag(fname, ftype, value, JVMCI_CHECK_NULL); \ JVMCIENV->put_object_at(vmFlags, i++, vmFlagObj); \ } -#define ADD_BOOL_FLAG(name) ADD_FLAG(bool, name, BOXED_BOOLEAN) -#define ADD_INT_FLAG(name) ADD_FLAG(int, name, BOXED_LONG) -#define ADD_INTX_FLAG(name) ADD_FLAG(intx, name, BOXED_LONG) -#define ADD_UINTX_FLAG(name) ADD_FLAG(uintx, name, BOXED_LONG) +#define ADD_BOOL_FLAG(name) ADD_FLAG(bool, name, BOXED_BOOLEAN) +#define ADD_INT_FLAG(name) ADD_FLAG(int, name, BOXED_LONG) +#define ADD_SIZE_T_FLAG(name) ADD_FLAG(size_t, name, BOXED_LONG) +#define ADD_INTX_FLAG(name) ADD_FLAG(intx, name, BOXED_LONG) +#define ADD_UINTX_FLAG(name) ADD_FLAG(uintx, name, BOXED_LONG) - len = 0 + PREDEFINED_CONFIG_FLAGS(COUNT_FLAG, COUNT_FLAG, COUNT_FLAG, COUNT_FLAG); + len = 0 + PREDEFINED_CONFIG_FLAGS(COUNT_FLAG, COUNT_FLAG, COUNT_FLAG, COUNT_FLAG, COUNT_FLAG); JVMCIObjectArray vmFlags = JVMCIENV->new_VMFlag_array(len, JVMCI_CHECK_NULL); int i = 0; JVMCIObject value; - PREDEFINED_CONFIG_FLAGS(ADD_BOOL_FLAG, ADD_INT_FLAG, ADD_INTX_FLAG, ADD_UINTX_FLAG) + PREDEFINED_CONFIG_FLAGS(ADD_BOOL_FLAG, ADD_INT_FLAG, ADD_SIZE_T_FLAG, ADD_INTX_FLAG, ADD_UINTX_FLAG) JVMCIObjectArray vmIntrinsics = CompilerToVM::initialize_intrinsics(JVMCI_CHECK_NULL); diff --git a/src/hotspot/share/memory/heap.cpp b/src/hotspot/share/memory/heap.cpp index b111c61f15a..a1333ed13e9 100644 --- a/src/hotspot/share/memory/heap.cpp +++ b/src/hotspot/share/memory/heap.cpp @@ -280,7 +280,7 @@ void* CodeHeap::allocate(size_t instance_size) { } // Ensure minimum size for allocation to the heap. - number_of_segments = MAX2((int)CodeCacheMinBlockLength, (int)number_of_segments); + number_of_segments = MAX2(CodeCacheMinBlockLength, number_of_segments); if (_next_segment + number_of_segments <= _number_of_committed_segments) { mark_segmap_as_used(_next_segment, _next_segment + number_of_segments, false); diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index a49116fd91d..5b56c81a32d 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -2448,7 +2448,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, JVMFlagOrigin "Invalid maximum code cache size: %s.\n", option->optionString); return JNI_EINVAL; } - if (FLAG_SET_CMDLINE(ReservedCodeCacheSize, (uintx)long_ReservedCodeCacheSize) != JVMFlag::SUCCESS) { + if (FLAG_SET_CMDLINE(ReservedCodeCacheSize, (size_t)long_ReservedCodeCacheSize) != JVMFlag::SUCCESS) { return JNI_EINVAL; } // -green diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp index 18aa4a56d71..0d93b380384 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp @@ -155,8 +155,8 @@ JVMFlag::Error OnStackReplacePercentageConstraintFunc(intx value, bool verbose) return JVMFlag::SUCCESS; } -JVMFlag::Error CodeCacheSegmentSizeConstraintFunc(uintx value, bool verbose) { - if (CodeCacheSegmentSize < (uintx)CodeEntryAlignment) { +JVMFlag::Error CodeCacheSegmentSizeConstraintFunc(size_t value, bool verbose) { + if (CodeCacheSegmentSize < (size_t)CodeEntryAlignment) { JVMFlag::printError(verbose, "CodeCacheSegmentSize (%zu) must be " "larger than or equal to CodeEntryAlignment (%zd) " @@ -174,7 +174,7 @@ JVMFlag::Error CodeCacheSegmentSizeConstraintFunc(uintx value, bool verbose) { } #ifdef COMPILER2 - if (CodeCacheSegmentSize < (uintx)OptoLoopAlignment) { + if (CodeCacheSegmentSize < (size_t)OptoLoopAlignment) { JVMFlag::printError(verbose, "CodeCacheSegmentSize (%zu) must be " "larger than or equal to OptoLoopAlignment (%zd) " @@ -203,7 +203,7 @@ JVMFlag::Error CodeEntryAlignmentConstraintFunc(intx value, bool verbose) { return JVMFlag::VIOLATES_CONSTRAINT; } - if ((uintx)CodeEntryAlignment > CodeCacheSegmentSize) { + if ((size_t)CodeEntryAlignment > CodeCacheSegmentSize) { JVMFlag::printError(verbose, "CodeEntryAlignment (%zd) must be " "less than or equal to CodeCacheSegmentSize (%zu) " diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp index cfca8ecf8ee..4544ad706fd 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ f(int, AllocatePrefetchStepSizeConstraintFunc) \ f(intx, CompileThresholdConstraintFunc) \ f(intx, OnStackReplacePercentageConstraintFunc) \ - f(uintx, CodeCacheSegmentSizeConstraintFunc) \ + f(size_t, CodeCacheSegmentSizeConstraintFunc) \ f(intx, CodeEntryAlignmentConstraintFunc) \ f(intx, OptoLoopAlignmentConstraintFunc) \ f(uintx, ArraycopyDstPrefetchDistanceConstraintFunc) \ diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp index f49b7f66690..9e0825339c9 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp @@ -99,8 +99,8 @@ JVMFlag::Error ContendedPaddingWidthConstraintFunc(int value, bool verbose) { } } -JVMFlag::Error VMPageSizeConstraintFunc(uintx value, bool verbose) { - uintx min = (uintx)os::vm_page_size(); +JVMFlag::Error VMPageSizeConstraintFunc(size_t value, bool verbose) { + size_t min = os::vm_page_size(); if (value < min) { JVMFlag::printError(verbose, "%s %s=%zu is outside the allowed range [ %zu" diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp index ddd2bae1914..5ca28a73fb0 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ f(ccstr, AOTModeConstraintFunc) \ f(int, ObjectAlignmentInBytesConstraintFunc) \ f(int, ContendedPaddingWidthConstraintFunc) \ - f(uintx, VMPageSizeConstraintFunc) \ + f(size_t, VMPageSizeConstraintFunc) \ f(size_t, NUMAInterleaveGranularityConstraintFunc) RUNTIME_CONSTRAINTS(DECLARE_CONSTRAINT) diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 75736d0dc7d..dc2889e5358 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1501,7 +1501,7 @@ const int ObjectAlignmentInBytes = 8; "Stack space (bytes) required for JVM_InvokeMethod to complete") \ \ /* code cache parameters */ \ - product_pd(uintx, CodeCacheSegmentSize, EXPERIMENTAL, \ + product_pd(size_t, CodeCacheSegmentSize, EXPERIMENTAL, \ "Code cache segment size (in bytes) - smallest unit of " \ "allocation") \ range(1, 1024) \ @@ -1516,38 +1516,38 @@ const int ObjectAlignmentInBytes = 8; range(1, 128) \ constraint(OptoLoopAlignmentConstraintFunc, AfterErgo) \ \ - product_pd(uintx, InitialCodeCacheSize, \ + product_pd(size_t, InitialCodeCacheSize, \ "Initial code cache size (in bytes)") \ constraint(VMPageSizeConstraintFunc, AtParse) \ \ - develop_pd(uintx, CodeCacheMinimumUseSpace, \ + develop_pd(size_t, CodeCacheMinimumUseSpace, \ "Minimum code cache size (in bytes) required to start VM.") \ - range(0, max_uintx) \ + range(0, SIZE_MAX) \ \ product(bool, SegmentedCodeCache, false, \ "Use a segmented code cache") \ \ - product_pd(uintx, ReservedCodeCacheSize, \ + product_pd(size_t, ReservedCodeCacheSize, \ "Reserved code cache size (in bytes) - maximum code cache size") \ constraint(VMPageSizeConstraintFunc, AtParse) \ \ - product_pd(uintx, NonProfiledCodeHeapSize, \ + product_pd(size_t, NonProfiledCodeHeapSize, \ "Size of code heap with non-profiled methods (in bytes)") \ - range(0, max_uintx) \ + range(0, SIZE_MAX) \ \ - product_pd(uintx, ProfiledCodeHeapSize, \ + product_pd(size_t, ProfiledCodeHeapSize, \ "Size of code heap with profiled methods (in bytes)") \ - range(0, max_uintx) \ + range(0, SIZE_MAX) \ \ - product_pd(uintx, NonNMethodCodeHeapSize, \ + product_pd(size_t, NonNMethodCodeHeapSize, \ "Size of code heap with non-nmethods (in bytes)") \ constraint(VMPageSizeConstraintFunc, AtParse) \ \ - product_pd(uintx, CodeCacheExpansionSize, \ + product_pd(size_t, CodeCacheExpansionSize, \ "Code cache expansion size (in bytes)") \ - range(32*K, max_uintx) \ + range(32*K, SIZE_MAX) \ \ - product_pd(uintx, CodeCacheMinBlockLength, DIAGNOSTIC, \ + product_pd(size_t, CodeCacheMinBlockLength, DIAGNOSTIC, \ "Minimum number of segments in a code cache block") \ range(1, 100) \ \ diff --git a/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java b/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java index 139ea6d76a2..06b51b1641d 100644 --- a/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java +++ b/test/hotspot/jtreg/compiler/codecache/CheckSegmentedCodeCache.java @@ -188,7 +188,7 @@ public static void main(String[] args) throws Exception { failsWith(pb, "Invalid code heap sizes"); // Fails if not enough space for VM internal code - long minUseSpace = WHITE_BOX.getUintxVMFlag("CodeCacheMinimumUseSpace"); + long minUseSpace = WHITE_BOX.getSizeTVMFlag("CodeCacheMinimumUseSpace"); // minimum size: CodeCacheMinimumUseSpace DEBUG_ONLY(* 3) long minSize = (Platform.isDebugBuild() ? 3 : 1) * minUseSpace; pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:+SegmentedCodeCache", diff --git a/test/hotspot/jtreg/compiler/codecache/jmx/CodeCacheUtils.java b/test/hotspot/jtreg/compiler/codecache/jmx/CodeCacheUtils.java index 340021bb993..ab017a9ecf0 100644 --- a/test/hotspot/jtreg/compiler/codecache/jmx/CodeCacheUtils.java +++ b/test/hotspot/jtreg/compiler/codecache/jmx/CodeCacheUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,9 +41,9 @@ public final class CodeCacheUtils { = Integer.getInteger("codecache.allocation.size", 100); public static final WhiteBox WB = WhiteBox.getWhiteBox(); public static final long SEGMENT_SIZE - = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheSegmentSize"); + = WhiteBox.getWhiteBox().getSizeTVMFlag("CodeCacheSegmentSize"); public static final long MIN_BLOCK_LENGTH - = WhiteBox.getWhiteBox().getUintxVMFlag("CodeCacheMinBlockLength"); + = WhiteBox.getWhiteBox().getSizeTVMFlag("CodeCacheMinBlockLength"); public static final long MIN_ALLOCATION = SEGMENT_SIZE * MIN_BLOCK_LENGTH; private CodeCacheUtils() { diff --git a/test/hotspot/jtreg/compiler/codecache/stress/RandomAllocationTest.java b/test/hotspot/jtreg/compiler/codecache/stress/RandomAllocationTest.java index 72e605397d0..26d3556d10e 100644 --- a/test/hotspot/jtreg/compiler/codecache/stress/RandomAllocationTest.java +++ b/test/hotspot/jtreg/compiler/codecache/stress/RandomAllocationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,7 @@ public class RandomAllocationTest implements Runnable { private static final long CODE_CACHE_SIZE - = Helper.WHITE_BOX.getUintxVMFlag("ReservedCodeCacheSize"); + = Helper.WHITE_BOX.getSizeTVMFlag("ReservedCodeCacheSize"); private static final int MAX_BLOB_SIZE = (int) (CODE_CACHE_SIZE >> 7); private static final BlobType[] BLOB_TYPES = BlobType.getAvailable().toArray(new BlobType[0]); diff --git a/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java b/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java index c66c2a22f14..a77b3681bf2 100644 --- a/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java +++ b/test/hotspot/jtreg/compiler/codecache/stress/ReturnBlobToWrongHeapTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,8 +48,8 @@ import java.util.ArrayList; public class ReturnBlobToWrongHeapTest { - private static final long largeBlobSize = Helper.WHITE_BOX.getUintxVMFlag("ReservedCodeCacheSize") >> 6; - private static final long codeCacheMinBlockLength = Helper.WHITE_BOX.getUintxVMFlag("CodeCacheMinBlockLength"); + private static final long largeBlobSize = Helper.WHITE_BOX.getSizeTVMFlag("ReservedCodeCacheSize") >> 6; + private static final long codeCacheMinBlockLength = Helper.WHITE_BOX.getSizeTVMFlag("CodeCacheMinBlockLength"); private static final BlobType[] BLOB_TYPES = BlobType.getAvailable().toArray(new BlobType[0]); // Allocate blob in first code heap (the code heap with index 0). diff --git a/test/hotspot/jtreg/compiler/whitebox/AllocationCodeBlobTest.java b/test/hotspot/jtreg/compiler/whitebox/AllocationCodeBlobTest.java index 29168a1e7e8..e19e91fd8ce 100644 --- a/test/hotspot/jtreg/compiler/whitebox/AllocationCodeBlobTest.java +++ b/test/hotspot/jtreg/compiler/whitebox/AllocationCodeBlobTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ public class AllocationCodeBlobTest { private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); private static final long CODE_CACHE_SIZE - = WHITE_BOX.getUintxVMFlag("ReservedCodeCacheSize"); + = WHITE_BOX.getSizeTVMFlag("ReservedCodeCacheSize"); private static final int SIZE = 1; public static void main(String[] args) { diff --git a/test/jdk/jdk/jfr/event/compiler/TestCodeCacheConfig.java b/test/jdk/jdk/jfr/event/compiler/TestCodeCacheConfig.java index defc9cba1be..1eb402f08ae 100644 --- a/test/jdk/jdk/jfr/event/compiler/TestCodeCacheConfig.java +++ b/test/jdk/jdk/jfr/event/compiler/TestCodeCacheConfig.java @@ -50,7 +50,7 @@ public class TestCodeCacheConfig { private final static String EVENT_NAME = EventNames.CodeCacheConfiguration; - private static final long CodeCacheExpectedSize = WhiteBox.getWhiteBox().getUintxVMFlag("ReservedCodeCacheSize"); + private static final long CodeCacheExpectedSize = WhiteBox.getWhiteBox().getSizeTVMFlag("ReservedCodeCacheSize"); public static void main(String[] args) throws Exception { Recording recording = new Recording(); diff --git a/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java b/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java index dd227489a0c..a4fc50b764d 100644 --- a/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java +++ b/test/jdk/jdk/jfr/event/compiler/TestCodeSweeper.java @@ -65,8 +65,8 @@ public class TestCodeSweeper { private static final String METHOD_NAME = "verifyFullEvent"; private static final String pathFull = EventNames.CodeCacheFull; private static final String pathFailure = 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 SEGMENT_SIZE = WhiteBox.getWhiteBox().getSizeTVMFlag("CodeCacheSegmentSize"); + public static final long MIN_BLOCK_LENGTH = WhiteBox.getWhiteBox().getSizeTVMFlag("CodeCacheMinBlockLength"); public static final long MIN_ALLOCATION = SEGMENT_SIZE * MIN_BLOCK_LENGTH; private static final double CACHE_USAGE_COEF = 0.95d; diff --git a/test/lib-test/jdk/test/whitebox/vm_flags/UintxTest.java b/test/lib-test/jdk/test/whitebox/vm_flags/UintxTest.java index 0996350adff..79f8678a1e2 100644 --- a/test/lib-test/jdk/test/whitebox/vm_flags/UintxTest.java +++ b/test/lib-test/jdk/test/whitebox/vm_flags/UintxTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ public class UintxTest { private static final String FLAG_NAME = "VerifyGCStartAt"; - private static final String FLAG_DEBUG_NAME = "CodeCacheMinimumUseSpace"; + private static final String FLAG_DEBUG_NAME = "StopInterpreterAt"; private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE, (1L << 32L) - 1L, 1L << 32L}; private static final Long[] EXPECTED_64 = TESTS; diff --git a/test/lib/jdk/test/whitebox/code/BlobType.java b/test/lib/jdk/test/whitebox/code/BlobType.java index 24ce9d96a41..a2290acc7b6 100644 --- a/test/lib/jdk/test/whitebox/code/BlobType.java +++ b/test/lib/jdk/test/whitebox/code/BlobType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,6 +103,6 @@ public static EnumSet getAvailable() { } public long getSize() { - return WhiteBox.getWhiteBox().getUintxVMFlag(sizeOptionName); + return WhiteBox.getWhiteBox().getSizeTVMFlag(sizeOptionName); } } From b52af182c43380186decd7e35625e42c7cafb8c2 Mon Sep 17 00:00:00 2001 From: Srinivas Vamsi Parasa Date: Wed, 18 Jun 2025 18:30:06 +0000 Subject: [PATCH 105/213] 8359386: Fix incorrect value for max_size of C2CodeStub when APX is used Reviewed-by: thartmann, shade, jbhateja, sviswanathan --- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 177be6e59f7..4317bb3d018 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -4655,6 +4655,7 @@ static void convertF2I_slowpath(C2_MacroAssembler& masm, C2GeneralStub(dst, src, slowpath_target, 23, convertF2I_slowpath); + // Using the APX extended general purpose registers increases the instruction encoding size by 1 byte. + int max_size = 23 + (UseAPX ? 1 : 0); + auto stub = C2CodeStub::make(dst, src, slowpath_target, max_size, convertF2I_slowpath); jcc(Assembler::equal, stub->entry()); bind(stub->continuation()); } From 982064e50ca6bbcfb7d1d619307921adc6f4fdcd Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Wed, 18 Jun 2025 18:43:38 +0000 Subject: [PATCH 106/213] 8359167: Remove unused test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java Reviewed-by: sspitsyn, lmesnik --- .../vmTestbase/nsk/share/jdb/Launcher.java | 6 +- .../vmTestbase/nsk/share/jpda/BindServer.java | 1847 ----------------- .../share/jpda/DebugeeArgumentHandler.java | 44 - .../nsk/share/jpda/DebugeeBinder.java | 4 +- .../nsk/share/jpda/DebugeeProcess.java | 4 +- .../vmTestbase/nsk/share/jpda/IOPipe.java | 10 +- 6 files changed, 11 insertions(+), 1904 deletions(-) delete mode 100644 test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java index 44e476d0be7..1735cc1e18d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jdb/Launcher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ /** * This class provides launching of jdb and debuggee in local - * or remote mode according to test command line options. + * mode according to test command line options. */ public class Launcher extends DebugeeBinder { @@ -94,7 +94,7 @@ public Launcher (JdbArgumentHandler argumentHandler, Log log) { } /** - * Defines mode (local or remote) and type of connector (default, launching, + * Defines mode (local) and type of connector (default, launching, * raw launching, attaching or listening) according to options * parsed by JdbArgumentHandler. And then launches jdb * and debuggee in defined mode. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java deleted file mode 100644 index 58a7ca2a703..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/BindServer.java +++ /dev/null @@ -1,1847 +0,0 @@ -/* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package nsk.share.jpda; - -import java.io.*; -import java.net.*; -import java.util.*; - -import nsk.share.*; - -/** - * BindServer is an utility to perform JPDA tests - * in remote mode across network. - *

    - * This utility should be started on remote host. It listens for connection - * from JPDA tests and launches debuggee VM on this host. - *

    - * BindServer works together with Binder used in - * the tests to incapsulate actions required for launching debuggee VM. - * See ProcessBinder and DebugeeArgumentHandler - * to know how run tests in local or remote mode across network or - * on an single host. - *

    - * BindServer is started on the debuggee host. - * It recognizes following command line options: - *

      - *
    • -bind.file=filename - configuration file - *
    • -verbose - print verbose messages - *
    - *

    - * Only required option is -bind.file, which points to the file - * where pairs of particular pathes are presented as they are seen from - * both hosts along with some other BindServer options. - * See execution.html to read more about format of bind-file. - * - * @see DebugeeBinder - * @see DebugeeArgumentHandler - */ -public final class BindServer { - - /** Version of BindServer implementation. */ - public static final long VERSION = 2; - - /** Timeout in milliseconds used for waiting for inner threads. */ - private static long THREAD_TIMEOUT = DebugeeBinder.THREAD_TIMEOUT; // milliseconds - - private static int PASSED = 0; - private static int FAILED = 2; - private static int JCK_BASE = 95; - - private static int TRACE_LEVEL_PACKETS = 10; - private static int TRACE_LEVEL_THREADS = 20; - private static int TRACE_LEVEL_ACTIONS = 30; - private static int TRACE_LEVEL_SOCKETS = 40; - private static int TRACE_LEVEL_IO = 50; - - private static String pathSeparator = System.getProperty("path.separator"); - private static String fileSeparator = System.getProperty("file.separator"); - - private static char pathSeparatorChar = pathSeparator.charAt(0); - private static char fileSeparatorChar = fileSeparator.charAt(0); - - private static Log log = null; - private static Log.Logger logger = null; - private static ArgumentHandler argHandler = null; - - private static String pathConvertions[][] = null; - - - private int totalRequests = 0; - private int acceptedRequests = 0; - private int unauthorizedRequests = 0; - private int busyRequests = 0; - - /** - * Start BindServer utility from command line. - * This method invokes run() and redirects output - * to System.err. - * - * @param argv list of command line arguments - */ - public static void main (String argv[]) { - System.exit(run(argv,System.err) + JCK_BASE); - } - - /** - * Start BindServer utility from JCK-compatible - * environment. - * - * @param argv list of command line arguments - * @param out outpur stream for log messages - * - * @return FAILED if error occured - * PASSED oterwise - */ - public static int run(String argv[], PrintStream out) { - return new BindServer().runIt(argv, out); - } - /** - * Perform execution of BindServer. - * This method handles command line arguments, starts seperate - * thread for listening connection from test on remote host, - * and waits for command "exit" from a user. - * Finally it closes all conections and prints connections - * statiscs. - * - * @param argv list of command line arguments - * @param out outpur stream for log messages - * - * @return FAILED if error occured - * PASSED oterwise - */ - private int runIt(String argv[], PrintStream out) { - try { - argHandler = new ArgumentHandler(argv); - } catch (ArgumentHandler.BadOption e) { - out.println("ERROR: " + e.getMessage()); - return FAILED; - } - - if (argHandler.getArguments().length > 0) { - out.println("ERROR: " + "Too many positional arguments in command line"); - return FAILED; - } - - log = new Log(out, argHandler); - logger = new Log.Logger(log, ""); - - logger.trace(TRACE_LEVEL_THREADS, "BindServer: starting main thread"); - - logger.display("Listening to port: " + argHandler.getBindPortNumber()); - logger.display("Authorizing host: " + argHandler.getDebuggerHost()); - - pathConvertions = new String[][] { - { "TESTED_JAVA_HOME", argHandler.getDebuggerJavaHome(), argHandler.getDebugeeJavaHome() }, - { "TESTBASE", argHandler.getDebuggerTestbase(), argHandler.getDebugeeTestbase() }, - { "WORKDIR", argHandler.getDebuggerWorkDir(), argHandler.getDebugeeWorkDir() } - }; - - logger.display("Translating pathes:"); - for (int i = 0; i < pathConvertions.length; i++) { - logger.display(pathConvertions[i][0] + ":" +"\n" - + " " + pathConvertions[i][1] + "\n" - + " =>" + "\n" - + " " + pathConvertions[i][2]); - } - - String windir = argHandler.getDebugeeWinDir(); - if (!(windir == null || windir.equals(""))) { - logger.display("Using WINDIR: \n" - + " " + argHandler.getDebugeeWinDir()); - } - - BufferedReader stdIn = new BufferedReader( - new InputStreamReader(System.in, System.getProperty("stdin.encoding"))); - try (ListeningThread listeningThread = new ListeningThread(this)) { - listeningThread.bind(); - listeningThread.start(); - - System.out.println("\n" - + "BindServer started" + "\n" - + "Type \"exit\" to shut down BindServer" - + "\n"); - - for (; ; ) { - try { - String userInput = stdIn.readLine(); - if (userInput == null || userInput.equals("exit") - || userInput.equals("quit")) { - logger.display("Shutting down BindServer"); - stdIn.close(); - stdIn = null; - break; - } else if (userInput.trim().equals("")) { - continue; - } else { - System.out.println("ERROR: Unknown command: " + userInput); - } - } catch (IOException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure("Caught exception while reading console command:\n\t" - + e); - } - } - - printSummary(System.out); - - logger.trace(TRACE_LEVEL_THREADS, "BindServer: exiting main thread"); - } - - return PASSED; - } - - /** - * Print usefull summary statistics about connections occured. - * - * @param out output stream for printing statistics - */ - private void printSummary(PrintStream out) { - out.println("\n" - + "Connections summary:" + "\n" - + " Tolal connections: " + totalRequests + "\n" - + " Accepted authorized: " + acceptedRequests + "\n" - + " Rejected unauthorized " + unauthorizedRequests + "\n" - + " Rejected being busy: " + busyRequests + "\n"); - }; - - /** - * Check if given path starts with the specified prefix taking - * into account difference between slashChar used in path - * and fileSeparatorChar used in prefix. - * - * @param path path to check - * @param prefix prefix to compare with - * @param slashChar file separator used in path - */ - private static boolean checkPathPrefix(String path, String prefix, char slashChar) { - int prefixLength = prefix.length(); - if (prefixLength > path.length()) { - return false; - } - for (int i = 0; i < prefixLength; i++) { - char pathChar = path.charAt(i); - char prefixChar = prefix.charAt(i); - - if (pathChar != prefixChar) { - if ((pathChar == slashChar || pathChar == fileSeparatorChar - || pathChar == '\\' || pathChar == '/') - && (prefixChar == slashChar || prefixChar == fileSeparatorChar - || prefixChar == '\\' || prefixChar == '/')) { - // do nothing - } else { - return false; - } - } - } - return true; - } - - /** - * Convert given path according to list of prefixes from - * pathConvertions table. - * - * @param path path for converting - * @param slash file separator used in path - * @param name path identifier used for error messages - * @param strict force throwing Failure if path is not matched - * - * @return string with the converted path - * - * @throws Failure if path does not matched for translation - */ - private static String convertPath(String path, String slash, String name, boolean strict) { - if (path == null) - return null; - - char slashChar = slash.charAt(0); - - for (int i = 0; i < pathConvertions.length; i++) { - String from = pathConvertions[i][1]; - String to = pathConvertions[i][2]; - if (checkPathPrefix(path, from, slashChar)) { - return (to + path.substring(from.length())).replace(slashChar, fileSeparatorChar); - } - } - if (strict) { - throw new Failure("Path not matched for translation " + name + ":\n\t" + path); - } - return path; - } - - /** - * Convert given list of pathes according to list of prefixes from - * pathConvertions table by invoking convertPath() - * for each path from the list. - * - * @param list list of pathes for converting - * @param slash file separator used in pathes - * @param name path identifier used for error messages - * @param strict force throwing Failure if some path is not matched - * - * @return list of strings with converted pathes - * - * @throws Failure if some path does not matched for translation - * - * @see #convertPath() - */ - private static String[] convertPathes(String[] list, String slash, String name, boolean strict) { - String[] converted = new String[list.length]; - for (int i = 0; i < list.length; i++) { - converted[i] = convertPath(list[i], slash, name, strict); - } - return converted; - } - - /** - * Pause current thread for specified amount of time in milliseconds, - * This method uses Object.wait(long) method as a reliable - * method which prevents whole VM from suspending. - * - * @param millisecs - amount of time in milliseconds - */ - private static void sleeping(int millisecs) { - Object obj = new Object(); - - synchronized(obj) { - try { - obj.wait(millisecs); - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - new Failure("Thread interrupted while sleeping:\n\t" + e); - } - } - } - - /** - * Wait for given thread finished for specified timeout or - * interrupt this thread if not finished. - * - * @param thr thread to wait for - * @param millisecs timeout in milliseconds - */ - private static void waitInterruptThread(Thread thr, long millisecs) { - if (thr != null) { - String name = thr.getName(); - try { - if (thr.isAlive()) { - logger.trace(TRACE_LEVEL_THREADS, "Waiting for thread: " + name); - thr.join(millisecs); - } - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure ("Thread interrupted while waiting for another thread:\n\t" - + e); - } finally { - if (thr.isAlive()) { - logger.trace(TRACE_LEVEL_THREADS, "Interrupting not finished thread: " + name); - thr.interrupt(); -/* - logger.display("Stopping not finished thread: " + thr); - thr.stop(); - */ - } - } - } - } - - /** - * Wait for given thread finished for default timeout - * THREAD_TIMEOUT and - * interrupt this thread if not finished. - * - * @param thr thread to wait for - */ - private static void waitInterruptThread(Thread thr) { - waitInterruptThread(thr, THREAD_TIMEOUT); - } - -///////// Thread listening a TCP/IP socket ////////// - - /** - * An inner thread used for listening connection from remote test - * and starting separate serving thread for each accepted connection. - * - * @see ServingThread - */ - private static class ListeningThread extends Thread implements AutoCloseable { - private volatile boolean shouldStop = false; - private volatile boolean closed = false; - - private BindServer owner = null; - private volatile ServingThread servingThread = null; - private volatile int taskCount = 0; - - private ObjectOutputStream socOut = null; - private ObjectInputStream socIn = null; - - private String autorizedHostName = argHandler.getDebuggerHost(); - private InetAddress autorizedInetAddresses[] = null; - private int port = argHandler.getBindPortNumber(); - private Socket socket = null; - private ServerSocket serverSocket = null; - private InetAddress clientInetAddr = null; - private String clientHostName = null; - private SocketConnection connection = null; - - /** - * Make listening thread for given BindServer object - * as an owner and bind it to listening port by invoking method - * bind(). - * - * @see bind() - */ - public ListeningThread(BindServer owner) { - super("ListeningThread"); - this.owner = owner; - try { - autorizedInetAddresses = InetAddress.getAllByName(autorizedHostName); - } catch (UnknownHostException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure("Cannot resolve DEBUGGER_HOST value: " + autorizedHostName); - } - } - - /** - * Bind ServerSocket to the specified port. - */ - public void bind() { - for (int i = 0; !shouldStop && i < DebugeeBinder.CONNECT_TRIES; i++) { - try { - logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: binding to server socket ..."); - // length of the queue = 2 - serverSocket = new ServerSocket(port, 2); - // timeout for the ServerSocket.accept() - serverSocket.setSoTimeout(DebugeeBinder.CONNECT_TRY_DELAY); - logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: socket bound: " + serverSocket); - logger.display("Bound to listening port"); - return; - } catch (BindException e) { - logger.display("Socket binding try #" + i + " failed:\n\t" + e); - sleeping(DebugeeBinder.CONNECT_TRY_DELAY); - } catch (IOException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure("Caught exception while binding to socket:\n\t" - + e); - } - } - throw new Failure("Unable to bind to socket after " - + DebugeeBinder.CONNECT_TRIES + " tries"); - } - - /** - * Accept socket connection from authorized remote host and - * start separate SrvingThread to handle each connection. - * Connection from unauthorized hosts or connections made while - * current connection is alive are rejected. - * - * @see ServingThread - * @see #llowConnection() - * @see allowServing() - */ - public void run() { - String reply = null; - - logger.trace(TRACE_LEVEL_THREADS, "ListeningThread: started"); - logger.display("Listening for connection from remote host"); - while(!(shouldStop || isInterrupted())) { - try { - try { - logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: waiting for connection from test"); - socket = serverSocket.accept(); - logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: connection accepted"); - } catch(InterruptedIOException e) { -// logger.trace(TRACE_LEVEL_SOCKETS, "ListeningThread: timeout of waiting for connection from test"); - continue; - } - owner.totalRequests++; - logger.display(""); - clientInetAddr = socket.getInetAddress(); - clientHostName = clientInetAddr.getHostName(); - logger.display("Connection #" + owner.totalRequests - + " requested from host: " + clientHostName); - connection = new SocketConnection(logger, "BindServer"); -// connection.setPingTimeout(DebugeeBinder.PING_TIMEOUT); - connection.setSocket(socket); - socket = null; - if (allowConnection()) { - if (allowServing()) { - owner.acceptedRequests++; - reply = "host authorized: " + clientHostName; - logger.display("Accepting connection #" + owner.acceptedRequests - + ": " + reply); - servingThread = new ServingThread(this, connection); - servingThread.start(); - cleanHostConnection(); - } else { - owner.busyRequests++; - reply = "BindServer is busy"; - logger.complain("Rejecting connection #" + owner.busyRequests - + ": " + reply); - connection.writeObject(new RequestFailed(reply)); - closeHostConnection(); - } - } else { - owner.unauthorizedRequests++; - reply = "host unauthorized: " + clientHostName; - logger.complain("Rejecting connection #" + owner.unauthorizedRequests - + ": " + reply); - connection.writeObject(new RequestFailed(reply)); - closeHostConnection(); - } - } catch (Exception e) { - logger.complain("Caught exception while accepting connection:\n" + e); - e.printStackTrace(log.getOutStream()); - } - } - logger.trace(TRACE_LEVEL_THREADS, "ListeningThread: exiting"); - closeConnection(); - } - - /** - * Check if the connection made is from authorized host. - * - * @return true if connection is allowed because host authorized - * false if connection is rejected because host unauthorized - */ - private boolean allowConnection() { - // check if local host from loopback address - if (autorizedHostName.equals("localhost")) - return clientInetAddr.isLoopbackAddress(); - - // check if equal hostname - if (autorizedHostName.equals(clientHostName)) - return true; - - // check if equal host address - for (int i = 0; i < autorizedInetAddresses.length; i++) { - if (clientInetAddr.equals(autorizedInetAddresses[i])) { - return true; - } - } - return false; - } - - /** - * Check if no current connection exists or it is dead. - * If current connection presents it will be tested by pinging - * remote host and aborted if host sends no reply. If an alive - * connection exists, new connection will be rejected. - * - * @return true if no alive connection exists - * false otherwise - */ - private boolean allowServing() { - if (servingThread == null) { - return true; - } - if (servingThread.done) { - return true; - } - if (!servingThread.isConnectionAlive()) { - logger.display("# WARNING: Previous connection from remote host is dead: aborting connection"); - servingThread.close(); - servingThread = null; - return true; - } - -/* - logger.complain("Previous connection from remote host is alive: starting new connection"); - servingThread = null; - return true; - */ - logger.complain("Previous connection from remote host is alive: reject new connection"); - return false; - } - - /** - * Wait for this thread finished - * for specified timeout or interrupt it. - * - * @param millis timeout in milliseconds - */ - public void waitForThread(long millis) { - shouldStop = true; - waitInterruptThread(this, millis); - } - - /** - * Close socket connection from remote host. - */ - private void closeHostConnection() { - if (connection != null) { - connection.close(); - } - if (socket != null) { - try { - socket.close(); - } catch (IOException e) { - logger.complain("Caught IOException while closing socket:\n\t" - + e); - } - socket = null; - } - } - - /** - * Assign to connection and socket objects - * but do not close them. - */ - private void cleanHostConnection() { - connection = null; - socket = null; - } - - /** - * Close all connections and sockets. - */ - private void closeConnection() { - closeHostConnection(); - if (serverSocket != null) { - try { - serverSocket.close(); - } catch (IOException e) { - logger.complain("Caught IOException while closing ServerSocket:\n\t" - + e); - } - serverSocket = null; - } - } - - /** - * Close thread by closing all connections and waiting - * for thread to finish. - * - * @see #closeConnection() - */ - @Override - public synchronized void close() { - if (closed) { - return; - } - try { - closeHostConnection(); - if (servingThread != null) { - servingThread.close(); - servingThread = null; - } - waitForThread(THREAD_TIMEOUT); - closeConnection(); - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "ListeningThread closed"); - } catch (Throwable e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while closing ListeningThread:\n\t" + e); - } - } - - } // ListeningThread - -///////// Thread working with a communication channel ////////// - - /** - * An internal thread for handling each connection from a test - * on remote host. It reads requests from test and starts separate - * LaunchingThread to execute each request. - * - * @see LaunchingThread - */ - private static class ServingThread extends Thread { - private volatile boolean shouldStop = false; - private volatile boolean closed = false; - private volatile boolean done = false; - - private ListeningThread owner = null; - private LaunchingThread launchingThread = null; - - private SocketConnection connection = null; - - /** - * Make serving thread with specified input/output connection streams - * and given Listenerthread as an owner. - * - * @param owner owner of this thread - * @param connection established socket connection with test - */ - public ServingThread(ListeningThread owner, SocketConnection connection) { - super("ServingThread"); - this.owner = owner; - this.connection = connection; - } - - /** - * Read requests from socket connection and start LaunchingThread - * to perform each requested action. - */ - public void run() { - logger.trace(TRACE_LEVEL_THREADS, "ServingThread: starting handling requests from debugger"); - try { - // sending OK(version) - logger.trace(TRACE_LEVEL_ACTIONS, "ServingThread: sending initial OK(VERSION) to debugger"); - connection.writeObject(new OK(VERSION)); - - // receiving TaskID(id) - logger.trace(TRACE_LEVEL_IO, "ServingThread: waiting for TaskID from debugger"); - Object taskID = connection.readObject(); - logger.trace(TRACE_LEVEL_IO, "ServingThread: received TaskID from debugger: " + taskID); - if (taskID instanceof TaskID) { - String id = ((TaskID)taskID).id; - owner.taskCount++; - logger.println("[" + owner.taskCount + "/" + owner.owner.totalRequests + "]: " + id); - } else { - throw new Failure("Unexpected TaskID received form debugger: " + taskID); - } - - // starting launching thread - launchingThread = new LaunchingThread(this, connection); - launchingThread.start(); - - // receiving and handling requests - while(!(shouldStop || isInterrupted())) { - logger.trace(TRACE_LEVEL_IO, "ServingThread: waiting for request from debugger"); - Object request = connection.readObject(); - logger.trace(TRACE_LEVEL_IO, "ServingThread: received request from debugger: " + request); - if (request == null) { - logger.display("Connection closed"); - break; - } else if (request instanceof Disconnect) { - logger.display("Closing connection by request"); - request = null; - break; - } else { - boolean success = false; - long timeToFinish = System.currentTimeMillis() + THREAD_TIMEOUT; - while (System.currentTimeMillis() < timeToFinish) { - if (launchingThread.doneRequest()) { - success = true; - logger.trace(TRACE_LEVEL_ACTIONS, "ServingThread: asking launching thread to handle request: " + request); - launchingThread.handleRequest(request); - break; - } - try { - launchingThread.join(DebugeeBinder.TRY_DELAY); - } catch (InterruptedException e) { - throw new Failure("ServingThread interrupted while waiting for LaunchingThread:\n\t" - + e); - } - } - if (!success) { - logger.complain("Rejecting request because of being busy:\n" + request); - connection.writeObject( - new RequestFailed("Busy with handling previous request")); - } - } - } - } catch (Exception e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while handling request:\n\t" + e); - } finally { - logger.trace(TRACE_LEVEL_THREADS, "ServingThread: exiting"); - closeConnection(); - done = true; - } - } - - /** - * Check if present socket connection is alive. - */ - private boolean isConnectionAlive() { - return (connection != null && connection.isConnected()); - } - - /** - * Wait for this thread finished - * for specified timeout or interrupt it. - * - * @param millis timeout in milliseconds - */ - public void waitForThread(long millis) { - shouldStop = true; - waitInterruptThread(this, millis); - } - - /** - * Close socket connection from remote host. - */ - private void closeConnection() { - if (connection != null) { - connection.close(); - } - if (launchingThread != null) { - launchingThread.handleRequest(null); - } - } - - /** - * Close thread closing socket connection and - * waiting for thread finished. - */ - public synchronized void close() { - if (closed) { - return; - } - closeConnection(); - if (launchingThread != null) { - launchingThread.close(); - launchingThread = null; - } - waitForThread(THREAD_TIMEOUT); - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "ServingThread closed"); - } - - } // ServingThread - -///////// Thread serving a particular Binder's request ////////// - - /** - * An internal thread to execute each request from a test on remote host. - * Requests are coming from ServingThread by invoking handleRequest(Object) - * method. - */ - private static class LaunchingThread extends Thread { - private volatile boolean shouldStop = false; - private volatile boolean closed = false; - public volatile boolean done = false; - - private ServingThread owner = null; -// private ProcessWaitingThread waitingThread = null; - private Process process = null; - - private StreamRedirectingThread stdoutRedirectingThread = null; - private StreamRedirectingThread stderrRedirectingThread = null; - - /** Notification about request occurence. */ - private volatile Object notification = new Object(); - /** Request to execute. */ - private volatile Object request = null; - /** Socket stream to send replies to. */ - private SocketConnection connection = null; - - /** - * Make thread for executing requests from a test and - * send reply. - * - * @param owner owner of this thread - * @connection socket connection for sending replies - */ - public LaunchingThread(ServingThread owner, SocketConnection connection) { - super("LaunchingThread"); - this.owner = owner; - this.connection = connection; - } - - /** - * Notify this thread that new request has come. - * - * @param request request to execute - */ - public void handleRequest(Object request) { - synchronized (notification) { - this.request = request; - notification.notifyAll(); - } - } - - /** - * Check if request has been executed. - */ - public boolean doneRequest() { - return done; - } - - /** - * Wait for request notification from ServingThread - * and execute an action according to the request. - * Request null means thread should finish. - */ - public void run() { - logger.trace(TRACE_LEVEL_THREADS, "LaunchingThread: started to handle request"); - done = true; - while (!isInterrupted()) { - // wait for new request notification - logger.trace(TRACE_LEVEL_ACTIONS, "LaunchingThread: waiting for request"); - synchronized (notification) { - try { - notification.wait(); - } catch (InterruptedException e) { - logger.complain("LaunchingThread interrupted while waiting for request:\n\t" - + e); - break; - } - } - - // execute the request - try { - logger.trace(TRACE_LEVEL_ACTIONS, "LaunchingThread: handling request: " + request); - if (request == null) { - break; - } else if (request instanceof LaunchDebugee) { - launchDebugee((LaunchDebugee)request); - } else if (request instanceof WaitForDebugee) { - waitForDebugee((WaitForDebugee)request); - } else if (request instanceof DebugeeExitCode) { - debugeeExitCode((DebugeeExitCode)request); - } else if (request instanceof KillDebugee) { - killDebugee((KillDebugee)request); - } else { - String reason = "Unknown request: " + request; - logger.complain(reason); - sendReply(new RequestFailed(reason)); - } - } catch (Exception e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while handling request:\n\t" + e); - } - done = true; - } - done = true; - logger.trace(TRACE_LEVEL_THREADS, "LaunchingThread: exiting"); - closeConnection(); - } - - /** - * Send given reply to remote test. - * - * @param reply reply object to send - */ - public void sendReply(Object reply) throws IOException { - connection.writeObject(reply); - } - - /** - * Send given output line to remote test. - * - * @param reply wrapper object for output line to send - */ - public void sendStreamMessage(RedirectedStream wrapper) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "Sending output line wrapper to debugger: " + wrapper); - if (connection.isConnected()) { - sendReply(wrapper); - } else { - logger.complain("NOT redirected: " + wrapper.line); - } - } - - /** - * Launch two StreamRedirectingThread threads to redirect - * stdin/stderr output of debuggee VM process via BindServer - * connection. - * - * @param process debuggee VM process - */ - private void launchStreamRedirectors(Process process) { - stdoutRedirectingThread = - new StdoutRedirectingThread(this, process.getInputStream(), - DebugeeProcess.DEBUGEE_STDOUT_LOG_PREFIX); - stdoutRedirectingThread.start(); - stderrRedirectingThread = - new StderrRedirectingThread(this, process.getErrorStream(), - DebugeeProcess.DEBUGEE_STDERR_LOG_PREFIX); - stderrRedirectingThread.start(); - } - - /** - * Execute request for launching debuggee. - * - * @param request request to execute - */ - private void launchDebugee(LaunchDebugee request) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "LaunchDebugee: handle request: " + request); - - if (process != null) { - logger.complain("Unable to launch debuggee: process already launched"); - sendReply(new RequestFailed("Debuggee process already launched")); - return; - } - - try { - String[] cmd = request.cmd; - cmd[0] = convertPath(cmd[0], request.slash, "TESTED_JAVA_HOME", true); - for (int i = 1; i < cmd.length; i++) { - cmd[i] = convertPath(cmd[i], request.slash, "JAVA_ARGS", false); - } - String workDir = convertPath(request.workDir, request.slash, "WORKDIR", true); - String[] classPathes = convertPathes(request.classPathes, request.slash, "CLASSPATH", true); - String windir = argHandler.getDebugeeWinDir(); - - boolean win = (!(windir == null || windir.equals(""))); - String[] envp = new String[win ? 3 : 1] ; - envp[0] = "CLASSPATH=" + ArgumentParser.joinArguments(classPathes, "", pathSeparator); - if (win) { - envp[1] = "WINDIR=" + windir; - envp[2] = "SystemRoot=" + windir; - } - - logger.display("Setting environment:\n" - + " " + ArgumentHandler.joinArguments(envp, "", "\n ")); - logger.display("Setting work dir:\n" - + " " + workDir); - logger.display("Launching debuggee:\n" - + " " + ArgumentHandler.joinArguments(cmd, "\"")); - - process = Runtime.getRuntime().exec(cmd, envp, new File(workDir)); - logger.display(" debuggee launched successfully"); - - launchStreamRedirectors(process); - } catch (Exception e) { - if (!(e instanceof Failure)) { - e.printStackTrace(log.getOutStream()); - } - logger.complain("Caught exception while launching debuggee:\n\t" + e); - sendReply(new CaughtException(e)); - return; - } - - sendReply(new OK()); - } - - /** - * Execute request for waiting for debuggee exited. - * - * @param request request to execute - */ - private void waitForDebugee(WaitForDebugee request) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "WaitForDebugee: handle request: " + request); - - if (process == null) { - String reply = "No debuggee process to wait for"; - logger.complain(reply); - sendReply(new RequestFailed(reply)); - return; - } - - logger.display("Waiting for debuggee to exit"); -/* - // because timeout is not supported now - // we do not use separate thread for waiting for process - // and so following lines are commented out - - waitingThread = new ProcessWaitingThread(); - logger.trace(TRACE_LEVEL_ACTIONS, "LaunchingThread: starting thread for waiting for debugee process"); - waitingThread.start(); - try { - waitingThread.join(request.timeout); - if (waitingThread.isAlive()) { - String reply = "Timeout exceeded while waiting for debuggee to exit"; - logger.complain(reply); - waitingThread.interrupt(); - sendReply(socOut, new RequestFailed(reply)); - return; - } - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while waiting for debuggee:\n\t" + e); - sendReply(new CaughtException(e)); - return; - } - int exitStatus = waitingThread.exitStatus; - waitingThread = null; - */ - int exitStatus; - try { - exitStatus = process.waitFor(); - waitForRedirectors(THREAD_TIMEOUT); - process.destroy(); - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while waiting for debuggee process to exit:\n\t" - + e); - sendReply(new CaughtException(e)); - return; - } - logger.display(" debuggee exited with exit status: " + exitStatus); - sendReply(new OK(exitStatus)); - } - - /** - * Execute request for returning debuggee exit code. - * - * @param request request to execute - */ - private void debugeeExitCode(DebugeeExitCode request) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "DebugeeExitCode: handle request: " + request); - - if (process == null) { - String reply = "No debuggee process to get exit code for"; - logger.complain(reply); - sendReply(new RequestFailed(reply)); - return; - } - - int exitStatus = 0; - try { - exitStatus = process.exitValue(); - } catch (IllegalThreadStateException e) { - logger.display("# WARNING: Caught exception while getting exit status of debuggee:\n\t" - + e); - sendReply(new CaughtException(e)); - return; - } - logger.trace(TRACE_LEVEL_ACTIONS, "DebugeeExitCode: return debuggee exit status: " + exitStatus); - sendReply(new OK(exitStatus)); - } - - /** - * Execute request for unconditional terminating debuggee process. - * - * @param request request to execute - */ - private void killDebugee(KillDebugee request) throws IOException { - logger.trace(TRACE_LEVEL_ACTIONS, "killDebugee: handle request: " + request); - - if (process == null) { - String reply = "No debuggee process to kill"; - logger.complain(reply); - sendReply(new RequestFailed(reply)); - return; - } - - logger.trace(TRACE_LEVEL_ACTIONS, "killDebugee: killing debuggee process"); - process.destroy(); - - logger.trace(TRACE_LEVEL_ACTIONS, "killDebugee: debuggee process killed"); - sendReply(new OK()); - } - - /** - * Terminate debigee VM process if still alive. - */ - private void terminateDebugeeAtExit() { - if (process != null) { - logger.trace(TRACE_LEVEL_ACTIONS, "Checking that debuggee process has exited correctly"); - try { - int value = process.exitValue(); - } catch (IllegalThreadStateException e) { - logger.complain("Debuggee process has not exited correctly: trying to kill it"); - process.destroy(); - try { - int value = process.exitValue(); - } catch (IllegalThreadStateException ie) { - logger.complain("Debuggee process is alive after killing it"); - } - process = null; - return; - } - logger.trace(TRACE_LEVEL_ACTIONS, "Debuggee process has exited correctly"); - } - } - - /** - * Wait for stream redirecting threads finished - * for specified timeout. - * - * @param millis timeout in milliseconds - */ - private void waitForRedirectors(long millis) { - try { - if (stdoutRedirectingThread != null) { - stdoutRedirectingThread.join(millis); - } - if (stderrRedirectingThread != null) { - stderrRedirectingThread.join(millis); - } - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while waiting for debuggee process exited:\n\t" - + e); - } - } - - /** - * Wait for this thread finished - * for specified timeout or interrupt it. - * - * @param millis timeout in milliseconds - */ - public void waitForThread(long millis) { - shouldStop = true; - handleRequest(null); - waitInterruptThread(this, millis); - } - - /** - * Close connection with debuggee. - */ - public void closeConnection() { - // no connections to close - } - - /** - * Close thread by closing all connections with debuggee, - * finishing all redirectors and wait for thread finished. - */ - public synchronized void close() { - if (closed) { - return; - } - closeConnection(); - terminateDebugeeAtExit(); - if (stdoutRedirectingThread != null) { - stdoutRedirectingThread.close(); - stdoutRedirectingThread = null; - } - if (stderrRedirectingThread != null) { - stderrRedirectingThread.close(); - stderrRedirectingThread = null; - } - waitForThread(THREAD_TIMEOUT); - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "LaunchingThread closed"); - } - - /** - * An inner thread for waiting for debuggee process exited - * and saving its exit status. (currently not used) - */ -/* - private class ProcessWaitingThread extends Thread { - int exitStatus = 0; - - ProcessWaitingThread() { - super("ProcessWaitingThread"); - } - - public void run() { - logger.trace(TRACE_LEVEL_THREADS, "ProcessWaitingThread: starting waiting for process"); - try { - exitStatus = process.waitFor(); - } catch (InterruptedException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while waiting for debuggee process:\n\t" - + e); - } - logger.trace(TRACE_LEVEL_ACTIONS, "ProcessWaitingThread: process finished with status: " + exitStatus); - logger.trace(TRACE_LEVEL_THREADS, "ProcessWaitingThread: exiting"); - } - - public synchronized void close() { - logger.trace(TRACE_LEVEL_THREADS, "ProcessWaitingThread closed"); - } - - } // ProcessWaitingThread - */ - } // LaunchingThread - -///////// Redirecting threads ///////// - - /** - * An abstract base class for internal threads which redirects stderr/stdout - * output from debuggee process via BindServer connection. - *

    - * Two derived classes will redirect stderr or stdout stream - * by enwrapping stream line by DebugeeStderr or - * DebugeeStderr objects. They should implement only one - * abstract method enwrapLine(String) to make the difference. - */ - public static abstract class StreamRedirectingThread extends Thread { - private volatile boolean shouldStop = false; - private volatile boolean closed = false; - - private LaunchingThread owner = null; - - private BufferedReader bin = null; - private String prefix = null; - - /** - * Make a thread to enwrap and redirect lines from specified - * input stream with given prefix. - * - * @param owner owner of this thread - * @param is input stream to redirect lines from - * @param prefix prefix to add to each line - */ - public StreamRedirectingThread(LaunchingThread owner, InputStream is, String prefix) { - super("StreamRedirectingThread"); - this.prefix = prefix; - this.owner = owner; - bin = new BufferedReader(new InputStreamReader(is)); - } - - /** - * Read lines from an input stream, enwrap them, and send to remote - * test via BindServer connection. - */ - public void run() { - logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread: starting redirect output stream"); - try { - String line; - logger.trace(TRACE_LEVEL_IO, "StreamRedirectingThread: waiting for line from debuggee output"); - while(!shouldStop) { - line = bin.readLine(); - if (line == null) - break; - owner.sendStreamMessage(enwrapLine(prefix + line)); - } - } catch (EOFException e) { - logger.display("Debuggee output stream closed by process"); - } catch (IOException e) { - e.printStackTrace(log.getOutStream()); - logger.display("# WARNING: Connection to debuggee output stream aborted:\n\t" + e); - } catch (Exception e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while redirecting debuggee output stream:\n\t" - + e); - } - logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread: exiting"); - closeConnection(); - } - - /** - * Envrap output line by the appropriate wrapper. - * @param line line to enwrap - */ - protected abstract RedirectedStream enwrapLine(String line); - - /** - * Wait for this thread finished or interrupt it. - * - * @param millis timeout in milliseconds - */ - public void waitForThread(long millis) { - shouldStop = true; - waitInterruptThread(this, millis); - } - - /** - * Close redirected process output stream. - */ - public void closeConnection() { - if (closed) { - return; - } - if (bin != null) { - try { - bin.close(); - } catch (IOException e) { - e.printStackTrace(log.getOutStream()); - logger.complain("Caught exception while closing debuggee output stream:\n\t" - + e); - } - bin = null; - } - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread closed"); - } - - /** - * Close thread by waiting redirected stream closed - * and finish the thread. - */ - public synchronized void close() { - if (closed) { - return; - } - waitForThread(THREAD_TIMEOUT); - closeConnection(); - closed = true; - logger.trace(TRACE_LEVEL_THREADS, "StreamRedirectingThread closed"); - } - - } // StreamRedirectingThread - - /** - * Particalar case of StreamRedirectingThread to redirect - * stderr stream by enwrapping lines into DebugeeStderr - * objects. - */ - private static class StderrRedirectingThread extends StreamRedirectingThread { - - /** - * Make a thread to redirect stderr output stream. - */ - StderrRedirectingThread(LaunchingThread owner, InputStream is, String prefix) { - super(owner, is, prefix); - setName("StderrRedirectingThread"); - } - - /** - * Enwrap given line into DebugeeStderr object. - */ - protected RedirectedStream enwrapLine(String line) { - return new DebugeeStderr(line); - } - - } - - /** - * Particalar case of StreamRedirectingThread to redirect - * stdout stream by enwrapping lines into DebugeeStdout - * objects. - */ - private static class StdoutRedirectingThread extends StreamRedirectingThread { - - /** - * Make a thread to redirect stdout output stream. - */ - StdoutRedirectingThread(LaunchingThread owner, InputStream is, String prefix) { - super(owner, is, prefix); - setName("StdoutRedirectingThread"); - } - - /** - * Enwrap given line into DebugeeStdout object. - */ - protected RedirectedStream enwrapLine(String line) { - return new DebugeeStdout(line); - } - - } - -///////// BinderServer's packets ////////// - - /** - * Base serializable object to transmit request or reply - * via BindServer connection. - */ - public static class Packet implements Serializable {} - - ///////// Binder's requests ////////// - - /** - * Base class to represent request to BindServer. - */ - public static abstract class Request extends Packet {} - - /** - * This class implements task identification command. - */ - public static class TaskID extends Request { - public String id; - - public TaskID(String id) { - this.id = id; - } - - public String toString() { - return "TaskID: id=" + id; - } - } - - /** - * This class implements a request for launching a debugee. - */ - public static class LaunchDebugee extends Request { - public String slash; // slash symbol used on debugger host - public String[] cmd; // command line arguments as seen on debugger host - public String workDir; // path to working directory as seen on debugger host - public String[] classPathes; // list of class pathes as seen on debugger host - - public LaunchDebugee(String[] cmd, String slash, String workDir, - String[] pathes, String[] classPathes, - String[] libPathes) { - this.cmd = cmd; - this.slash = slash; - this.workDir = workDir; - this.classPathes = classPathes; - } - - public String toString() { - return "LaunchDebugee:" - + "\n\tcommand=" + ArgumentParser.joinArguments(cmd, "\"") - + "\n\tWORKDIR=" + workDir - + "\n\tCLASSPATH=" + ArgumentParser.joinArguments(classPathes, "", ":") - + "\n\tslash=" + slash; - } - } - - /** - * This class implements a request for waiting for debugee - * termination. - */ - public static class WaitForDebugee extends Request { - public long timeout = 0; // timeout in minutes for waiting - - public WaitForDebugee(long value) { - timeout = value; - } - - public String toString() { - return "WaitForDebugee: timeout=" + timeout; - } - } - - /** - * This class implements a request for exit code of - * debugee process. - */ - public static class DebugeeExitCode extends Request { - public String toString() { - return "SebugeeExitCode"; - } - } - - /** - * This class implements a request for killing debugee process. - */ - public static class KillDebugee extends Request { - public String toString() { - return "KillDebugee"; - } - } - - /** - * This class implements a request to disconnect connection with test. - */ - public static class Disconnect extends Request { - public String toString() { - return "Disconnect"; - } - } - - ///////// BindServer's responses ////////// - - /** - * Base class to represent response from BindServer. - */ - public static abstract class Response extends Packet {} - - /** - * This class implements a response that a previoulsy received - * request has been successfully performed. - */ - public static class OK extends Response { - public long info = BindServer.VERSION; // optional additional info - - public OK() { - } - - public OK(long value) { - info = value; - } - - public String toString() { - return "OK(" + info + ")"; - } - } - - /** - * This class implements a response that the BindServer is - * unable to serve a previoulsy received request. - */ - public static class RequestFailed extends Response { - public String reason; // the short explanation of failure - - public RequestFailed(String reason) { - this.reason = reason; - } - - public String toString() { - return "RequestFailed(" + reason + ")"; - } - } - - /** - * This class implements a response that the BindServer is - * unable to serve a previoulsy received request because of - * caught exception. - */ - public static class CaughtException extends RequestFailed { - public CaughtException(Exception cause) { - super("Caught exception: " + cause); - } - } - - ///////// Wrappers for redirected messages ////////// - - /** - * Base class to represent wrappers for redirected streams. - */ - public static class RedirectedStream extends Packet { - public String line; // line containing line from redirected stream - - public RedirectedStream(String str) { - line = str; - } - - public String toString() { - return "RedirectedStream(" + line + ")"; - } - } - - /** - * This class enwraps redirected line of stdout stream. - */ - public static class DebugeeStdout extends RedirectedStream { - - public DebugeeStdout(String str) { - super(str); - } - - public String toString() { - return "DebugeeStdout(" + line + ")"; - } - } - - /** - * This class enwraps redirected line of stderr stream. - */ - public static class DebugeeStderr extends RedirectedStream { - public DebugeeStderr(String str) { - super(str); - } - - public String toString() { - return "DebugeeStderr(" + line + ")"; - } - } - -/////// ArgumentHandler for BindServer command line ///////// - - /** - * This class is used to parse arguments from command line - * and specified bind-file, - */ - private static class ArgumentHandler extends ArgumentParser { - - protected Properties fileOptions; - - /** - * Make parser object for command line arguments. - * - * @param args list of command line arguments - */ - public ArgumentHandler(String[] args) { - super(args); - } - - /** - * Check if given command line option is aloowed. - * - * @param option option name - * @param value option value - */ - protected boolean checkOption(String option, String value) { - if (option.equals("bind.file")) { - // accept any file name - return true; - } - return super.checkOption(option, value); - } - - /** - * Check if all recignized options are compatible. - */ - protected void checkOptions() { - if (getBindFileName() == null) { - throw new BadOption("Option -bind.file is requred "); - } - super.checkOptions(); - } - - /** - * Check if value of this option points to a existing directory. - * - * @param option option name - * @param dir option value - */ - private void checkDir(String option, String dir) { - File file = new File(dir); - if (!file.exists()) { - throw new BadOption(option + " does not exist: " + dir); - } - if (!file.isAbsolute()) { - throw new BadOption(option + " is not absolute pathname: " + dir); - } - if (!file.isDirectory()) { - throw new BadOption(option + " is not directory: " + dir); - } - } - - /** - * Check if option from bind-file is allowed. - * - * @param option option name - * @param value option value - */ - protected boolean checkAdditionalOption(String option, String value) { - - if (option.equals("DEBUGGER_HOST")) { - // accept any hostname - return true; - } - - if (option.equals("BINDSERVER_PORT")) { - // accept only integer value - try { - int port = Integer.parseInt(value); - } catch (NumberFormatException e) { - throw new Failure("Not integer value of bind-file option " + option - + ": " + value); - } - return true; - } - - if (option.equals("DEBUGGER_TESTED_JAVA_HOME") - || option.equals("DEBUGGER_WORKDIR") - || option.equals("DEBUGGER_TESTBASE")) { - if (value == null || value.equals("")) { - throw new BadOption("Empty value of bind-file option " + option); - } - return true; - } - - if (option.equals("DEBUGGEE_TESTED_JAVA_HOME") - || option.equals("DEBUGGEE_WORKDIR") - || option.equals("DEBUGGEE_TESTBASE")) { - if (value == null || value.equals("")) { - throw new BadOption("Empty value of bind-file option " + option); - } - checkDir(option, value); - return true; - } - - if (option.equals("DEBUGGEE_WINDIR")) { - if (!(value == null || value.equals(""))) { - checkDir(option, value); - } - return true; - } - - return false; - } - - /** - * Check if all recignized options form bind-file are compatible. - */ - protected void checkAdditionalOptions() { - - if (getDebuggerJavaHome() == null) { - throw new BadOption("Option DEBUGGER_JAVA_HOME missed from bind-file"); - } - if (getDebuggerWorkDir() == null) { - throw new BadOption("Option DEBUGGER_WORKDIR missed from bind-file"); - } - if (getDebuggerTestbase() == null) { - throw new BadOption("Option DEBUGGER_TESTBASE missed from bind-file"); - } - - if (getDebugeeJavaHome() == null) { - throw new BadOption("Option DEBUGGEE_JAVA_HOME missed from bind-file"); - } - if (getDebugeeWorkDir() == null) { - throw new BadOption("Option DEBUGGEE_WORKDIR missed from bind-file"); - } - if (getDebugeeTestbase() == null) { - throw new BadOption("Option DEBUGGEE_TESTBASE missed from bind-file"); - } - } - - /** - * Parse options form specified bind-file. - */ - protected void parseAdditionalOptions() { - Enumeration keys = fileOptions.keys(); - while (keys.hasMoreElements()) { - String option = (String)keys.nextElement(); - String value = fileOptions.getProperty(option); - if (! checkAdditionalOption(option, value)) { - throw new BadOption("Unrecognized bind-file option: " + option); - } - } - checkAdditionalOptions(); - } - - /** - * Parse all options from command line and specified bind-file. - */ - protected void parseArguments() { - super.parseArguments(); - String fileName = getBindFileName(); - try { - FileInputStream bindFile = new FileInputStream(fileName); - fileOptions = new Properties(); - fileOptions.load(bindFile); - bindFile.close(); - } catch(FileNotFoundException e) { - throw new BadOption("Unable to open bind-file " + fileName + ": " + e); - } catch(IOException e) { - e.printStackTrace(log.getOutStream()); - throw new Failure("Caught exception while reading bind-file:\n" + e); - } - parseAdditionalOptions(); - } - - /** Return name of specified bind-file. */ - public String getBindFileName() { - return options.getProperty("bind.file"); - } - - /** Return specified debuggee host name . */ - public String getDebuggerHost() { - return fileOptions.getProperty("DEBUGGER_HOST", "localhost"); - } - - /** Return string representation of port number for BindServer connection. */ - public String getBindPort() { - return fileOptions.getProperty("BINDSERVER_PORT", "9000"); - } - - /** Return specified port number for BindServer connection. */ - public int getBindPortNumber() { - try { - return Integer.parseInt(getBindPort()); - } catch (NumberFormatException e) { - throw new Failure("Not integer value of BindServer port"); - } - } - - /** Return specified path to tested JDK used for debuggee VM. */ - public String getDebugeeJavaHome() { - return fileOptions.getProperty("DEBUGGEE_TESTED_JAVA_HOME"); - } - - /** Return specified path to tested JDK used for debugger. */ - public String getDebuggerJavaHome() { - return fileOptions.getProperty("DEBUGGER_TESTED_JAVA_HOME"); - } - - /** Return specified path to working dir from debuggee host. */ - public String getDebugeeWorkDir() { - return fileOptions.getProperty("DEBUGGEE_WORKDIR"); - } - - /** Return specified path to working dir from debugger host. */ - public String getDebuggerWorkDir() { - return fileOptions.getProperty("DEBUGGER_WORKDIR"); - } - - /** Return specified path to testbase dir from debuggee host. */ - public String getDebugeeTestbase() { - return fileOptions.getProperty("DEBUGGEE_TESTBASE"); - } - - /** Return specified path to testbase dir from debugger host. */ - public String getDebuggerTestbase() { - return fileOptions.getProperty("DEBUGGER_TESTBASE"); - } - - /** Return specified path to system directory on Wimdows platform. */ - public String getDebugeeWinDir() { - return fileOptions.getProperty("DEBUGGEE_WINDIR"); - } - - } // ArgumentHandler - -} // BindServer diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java index 72b8076f927..05d0054928b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeArgumentHandler.java @@ -67,8 +67,6 @@ * using JVMDI strict mode *

  • -pipe.port=<port> - * port number for internal IOPipe connection - *
  • -bind.port=<port> - - * port number for BindServer connection * *

    * See also list of basic options recognized by @@ -421,47 +419,6 @@ public boolean isDefaultDebugeeJavaHome() { return (java_home == null); } - private boolean bindPortInited = false; - /** - * Return string representation of the port number for BindServer connection, - * specified by -bind.port command line option, or - * "DEFAULT_BIND_PORT" string by default. - * - * @see #getBindPortNumber() - * @see #setRawArguments(String[]) - */ - public String getBindPort() { - String port = options.getProperty("bind.port"); - if (port == null) { - if (!bindPortInited) { - port = findFreePort(); - if (port == null) { - port = DEFAULT_BIND_PORT; - } - options.setProperty("bind.port", port); - bindPortInited = true; - } - } - return port; - } - - /** - * Return port number for BindServer connection, - * specified by -bind.port command line option, or - * "DEFAULT_BIND_PORT" port number by default. - * - * @see #getBindPort() - * @see #setRawArguments(String[]) - */ - public int getBindPortNumber() { - String value = getBindPort(); - try { - return Integer.parseInt(value); - } catch (NumberFormatException e) { - throw new TestBug("Not integer value of \"bind.port\" argument: " + value); - } - } - /** * Return JVMDI strict mode for launching debugee VM, specified by. * -jvmdi.strict command line option, or @@ -683,7 +640,6 @@ protected boolean checkOption(String option, String value) { // option with positive integer port value if (option.equals("transport.port") - || option.equals("bind.port") || option.equals("pipe.port")) { try { int number = Integer.parseInt(value); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java index d36c9d9624f..d04fed1bd32 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeBinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,8 +52,8 @@ * @see DebugeeArgumentHandler * @see DebugeeProcess * @see IOPipe - * @see BindServer * + * @see nsk.share.jdb.Launcher * @see nsk.share.jdi.Binder * @see nsk.share.jdwp.Binder */ diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java index b875911e973..55ee5366582 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/DebugeeProcess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ * This is an abstract class that declares abstract methods to control * debugee VM process. * Derived classes should implement these methods corresponding to the mode - * that the process should be started in (locally, remotely or manually). + * that the process should be started in (locally). *

    * Particular derived classes nsk.share.jdi.Debugee and * nsk.share.jdwp.Debugee provides additional abilities diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java index 74e3a7c3a6d..062b8a4ba4d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/IOPipe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,12 +29,10 @@ /** * This class implements communicational channel between * debugger and debugee used for synchronization and data exchange. - * This channel is based on TCP/IP sockets and works in all - * modes (local, remote and manual). In a remote mode - * connection to BindServer is used for redirecting IOPipe messages. - * In all other modes direct TCP/IP coonnection between two VMs is used. + * This channel is based on TCP/IP sockets. * - * @see BindServer + * @see jpda.DebugeeArgumentHandler + * @see jpda.DebugeeProcess */ public class IOPipe extends SocketIOPipe { From 5a62e99523904e89caf561d4c1068c1565a97450 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Wed, 18 Jun 2025 20:58:01 +0000 Subject: [PATCH 107/213] 8357686: Remove unnecessary Map.get from AWTAutoShutdown.unregisterPeer Reviewed-by: serb, aivanov --- src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java b/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java index 5a81de507db..d60211ae318 100644 --- a/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java +++ b/src/java.desktop/share/classes/sun/awt/AWTAutoShutdown.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -358,8 +358,7 @@ void registerPeer(final Object target, final Object peer) { void unregisterPeer(final Object target, final Object peer) { synchronized (activationLock) { synchronized (mainLock) { - if (peerMap.get(target) == peer) { - peerMap.remove(target); + if (peerMap.remove(target, peer)) { notifyPeerMapUpdated(); } } From 23e1e2ff4a4a75ec268c7925fb98d6b96a01bbcf Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 18 Jun 2025 22:54:05 +0000 Subject: [PATCH 108/213] 8359180: Apply java.io.Serial annotations in java.instrument Reviewed-by: phh, sspitsyn --- .../java/lang/instrument/IllegalClassFormatException.java | 6 +++++- .../java/lang/instrument/UnmodifiableClassException.java | 6 +++++- .../java/lang/instrument/UnmodifiableModuleException.java | 7 +++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/java.instrument/share/classes/java/lang/instrument/IllegalClassFormatException.java b/src/java.instrument/share/classes/java/lang/instrument/IllegalClassFormatException.java index 7e14665b198..59bde2f6c1f 100644 --- a/src/java.instrument/share/classes/java/lang/instrument/IllegalClassFormatException.java +++ b/src/java.instrument/share/classes/java/lang/instrument/IllegalClassFormatException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.lang.instrument; +import java.io.Serial; + /* * Copyright 2003 Wily Technology, Inc. */ @@ -40,6 +42,8 @@ * @since 1.5 */ public class IllegalClassFormatException extends Exception { + + @Serial private static final long serialVersionUID = -3841736710924794009L; /** diff --git a/src/java.instrument/share/classes/java/lang/instrument/UnmodifiableClassException.java b/src/java.instrument/share/classes/java/lang/instrument/UnmodifiableClassException.java index d6aac1d5b4b..40bae4b5c91 100644 --- a/src/java.instrument/share/classes/java/lang/instrument/UnmodifiableClassException.java +++ b/src/java.instrument/share/classes/java/lang/instrument/UnmodifiableClassException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package java.lang.instrument; +import java.io.Serial; + /** * Thrown by an implementation of * {@link java.lang.instrument.Instrumentation#redefineClasses Instrumentation.redefineClasses} @@ -34,6 +36,8 @@ * @since 1.5 */ public class UnmodifiableClassException extends Exception { + + @Serial private static final long serialVersionUID = 1716652643585309178L; /** diff --git a/src/java.instrument/share/classes/java/lang/instrument/UnmodifiableModuleException.java b/src/java.instrument/share/classes/java/lang/instrument/UnmodifiableModuleException.java index 462ee8b71ff..f97294a01c1 100644 --- a/src/java.instrument/share/classes/java/lang/instrument/UnmodifiableModuleException.java +++ b/src/java.instrument/share/classes/java/lang/instrument/UnmodifiableModuleException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,17 @@ package java.lang.instrument; +import java.io.Serial; + /** * Thrown to indicate that a module cannot be modified. * * @see Instrumentation#redefineModule * @since 9 */ - public class UnmodifiableModuleException extends RuntimeException { + + @Serial private static final long serialVersionUID = 6912511912351080644L; /** From 08b1fa4cb39e56497052e3ee13e679c8734cf7c5 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Thu, 19 Jun 2025 05:35:51 +0000 Subject: [PATCH 109/213] 8359972: Problem list TestStaticCallStub until JDK-8359963 is fixed Reviewed-by: mchevalier, chagedorn --- 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 ac51090aaa8..1f62bfa8f29 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -79,6 +79,8 @@ compiler/ciReplay/TestIncrementalInlining.java 8349191 generic-all compiler/c2/TestVerifyConstraintCasts.java 8355574 generic-all +compiler/c2/aarch64/TestStaticCallStub.java 8359963 linux-aarch64,macosx-aarch64 + ############################################################################# # :hotspot_gc From 0dce98b71648f270dca7395e7ab5451011b14b45 Mon Sep 17 00:00:00 2001 From: Ana Maria Mihalceanu Date: Thu, 19 Jun 2025 07:45:04 +0000 Subject: [PATCH 110/213] 8359123: Misleading examples in jmod man page Reviewed-by: cstein, alanb, iris --- src/jdk.jlink/share/man/jmod.md | 38 ++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/src/jdk.jlink/share/man/jmod.md b/src/jdk.jlink/share/man/jmod.md index 6fd2aa54cf9..4e20e2458b7 100644 --- a/src/jdk.jlink/share/man/jmod.md +++ b/src/jdk.jlink/share/man/jmod.md @@ -1,5 +1,5 @@ --- -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -179,7 +179,11 @@ e.g. "2022-02-12T12:30:00-05:00". `--hash-modules`. `--target-platform` *platform* -: Specifies the target platform. +: Specifies the target platform of a JMOD file intended for a specific + operating system and architecture. The value should follow + the format `-`, where `` is the operating system + and `` is the hardware architecture. Example values include + `linux-amd64`, `windows-amd64`, and `macos-aarch64`. `--version` : Prints version information of the `jmod` tool. @@ -190,7 +194,7 @@ e.g. "2022-02-12T12:30:00-05:00". An options file is a text file that contains the options and values that you would ordinarily enter in a command prompt. Options may appear on one line or on several lines. You may not specify environment variables for - path names. You may comment out lines by prefixinga hash symbol (`#`) to + path names. You may comment out lines by prefixing a hash symbol (`#`) to the beginning of the line. The following is an example of an options file for the `jmod` command: @@ -201,8 +205,7 @@ e.g. "2022-02-12T12:30:00-05:00". --cmds commands --config configfiles --header-files src/h --libs lib --main-class com.greetings.Main --man-pages man --module-version 1.0 - --os-arch "x86_x64" --os-name "macOS" - --os-version "10.10.5" greetingsmod + --target-platform "macos-aarch64" greetingsmod ``` ## Extra Options for jmod @@ -217,23 +220,32 @@ extra options that can be used with the command. : Hint for a tool to issue a warning if the module is resolved. One of deprecated, deprecated-for-removal, or incubating. -## jmod Create Example +## jmod Create Examples -The following is an example of creating a JMOD file: +Create a JMOD file containing only compiled classes: ``` -jmod create --class-path mods/com.greetings --cmds commands - --config configfiles --header-files src/h --libs lib - --main-class com.greetings.Main --man-pages man --module-version 1.0 - --os-arch "x86_x64" --os-name "macOS" - --os-version "10.10.5" greetingsmod +jmod create --class-path build/foo/classes jmods/foo1.jmod ``` + Create a JMOD file specifying the date for the entries as `2022 March 15 00:00:00`: ``` jmod create --class-path build/foo/classes --date 2022-03-15T00:00:00Z - jmods/foo1.jmod + jmods/foo2.jmod +``` + +Create a JMOD file bundling compiled classes, native commands, configuration files, +header files, native libraries, man pages, and metadata including the +main class, module version, and target platform details: + ``` +jmod create --class-path mods/com.greetings --cmds commands + --config configfiles --header-files src/h --libs lib + --man-pages man --main-class com.greetings.Main --module-version 1.0 + --target-platform "macos-aarch64" greetingsmod +``` + ## jmod Hash Example The following example demonstrates what happens when you try to link a leaf From c7125aa2af43a339d401f8416a2251574f6de840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Thu, 19 Jun 2025 09:36:29 +0000 Subject: [PATCH 111/213] 8020282: Generated code quality: redundant LEAs in the chained dereferences MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Roberto Castañeda Lozano Reviewed-by: kvn, rcastanedalo --- src/hotspot/cpu/x86/peephole_x86_64.cpp | 138 +++++++ src/hotspot/cpu/x86/peephole_x86_64.hpp | 2 + src/hotspot/cpu/x86/x86_64.ad | 18 + .../compiler/codegen/TestRedundantLea.java | 382 ++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 16 + .../vm/compiler/x86/RedundantLeaPeephole.java | 112 +++++ 6 files changed, 668 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/x86/RedundantLeaPeephole.java diff --git a/src/hotspot/cpu/x86/peephole_x86_64.cpp b/src/hotspot/cpu/x86/peephole_x86_64.cpp index 2197055d1ec..59188962d0c 100644 --- a/src/hotspot/cpu/x86/peephole_x86_64.cpp +++ b/src/hotspot/cpu/x86/peephole_x86_64.cpp @@ -24,6 +24,7 @@ #ifdef COMPILER2 +#include "opto/addnode.hpp" #include "peephole_x86_64.hpp" #include "adfiles/ad_x86.hpp" @@ -235,6 +236,143 @@ bool Peephole::test_may_remove(Block* block, int block_index, PhaseCFG* cfg_, Ph return false; } +// This function removes redundant lea instructions that result from chained dereferences that +// match to leaPCompressedOopOffset, leaP8Narrow, or leaP32Narrow. This happens for ideal graphs +// of the form LoadN -> DecodeN -> AddP. Matching with any leaP* rule consumes both the AddP and +// the DecodeN. However, after matching the DecodeN is added back as the base for the leaP*, +// which is necessary if the oop derived by the leaP* gets added to an OopMap, because OopMaps +// cannot contain derived oops with narrow oops as a base. +// This results in the following graph after matching: +// LoadN +// | \ +// | decodeHeapOop_not_null +// | / \ +// leaP* MachProj (leaf) +// The decode_heap_oop_not_null will emit a lea with an unused result if the derived oop does +// not end up in an OopMap. +// This peephole recognizes graphs of the shape as shown above, ensures that the result of the +// decode is only used by the derived oop and removes that decode if this is the case. Further, +// multiple leaP*s can have the same decode as their base. This peephole will remove the decode +// if all leaP*s and the decode share the same parent. +// Additionally, if the register allocator spills the result of the LoadN we can get such a graph: +// LoadN +// | +// DefinitionSpillCopy +// / \ +// MemToRegSpillCopy MemToRegSpillCopy +// | / +// | decodeHeapOop_not_null +// | / \ +// leaP* MachProj (leaf) +// In this case where the common parent of the leaP* and the decode is one MemToRegSpillCopy +// away, this peephole can also recognize the decode as redundant and also remove the spill copy +// if that is only used by the decode. +bool Peephole::lea_remove_redundant(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_, + MachNode* (*new_root)(), uint inst0_rule) { + MachNode* lea_derived_oop = block->get_node(block_index)->as_Mach(); + assert(lea_derived_oop->rule() == inst0_rule, "sanity"); + assert(lea_derived_oop->ideal_Opcode() == Op_AddP, "sanity"); + + MachNode* decode = lea_derived_oop->in(AddPNode::Base)->isa_Mach(); + if (decode == nullptr || decode->ideal_Opcode() != Op_DecodeN) { + return false; + } + + // Check that the lea and the decode live in the same block. + if (!block->contains(decode)) { + return false; + } + + Node* lea_address = lea_derived_oop->in(AddPNode::Address); + Node* decode_address = decode->in(1); + + bool is_spill = lea_address != decode_address && + lea_address->is_SpillCopy() && + decode_address->is_SpillCopy(); + + // If this is a spill, move lea_address and decode_address one node further up to the + // grandparents of lea_derived_oop and decode respectively. This lets us look through + // the indirection of the spill. + if (is_spill) { + decode_address = decode_address->in(1); + lea_address = lea_address->in(1); + } + + // The leaP* and the decode must have the same parent. If we have a spill, they must have + // the same grandparent. + if (lea_address != decode_address) { + return false; + } + + // Ensure the decode only has the leaP*s (with the same (grand)parent) and a MachProj leaf as children. + MachProjNode* proj = nullptr; + for (DUIterator_Fast imax, i = decode->fast_outs(imax); i < imax; i++) { + Node* out = decode->fast_out(i); + if (out == lea_derived_oop) { + continue; + } + if (out->is_MachProj() && out->outcnt() == 0) { + proj = out->as_MachProj(); + continue; + } + if (out->is_Mach()) { + MachNode* other_lea = out->as_Mach(); + if ((other_lea->rule() == leaP32Narrow_rule || + other_lea->rule() == leaP8Narrow_rule || + other_lea->rule() == leaPCompressedOopOffset_rule) && + other_lea->in(AddPNode::Base) == decode && + (is_spill ? other_lea->in(AddPNode::Address)->in(1) + : other_lea->in(AddPNode::Address)) == decode_address) { + continue; + } + } + // There is other stuff we do not expect... + return false; + } + + // Ensure the MachProj is in the same block as the decode and the lea. + if (proj == nullptr || !block->contains(proj)) { + // This should only fail if we are stressing scheduling. + assert(StressGCM, "should be scheduled contiguously otherwise"); + return false; + } + + // We now have verified that the decode is redundant and can be removed with a peephole. + // Remove the projection + block->find_remove(proj); + cfg_->map_node_to_block(proj, nullptr); + + // Rewire the base of all leas currently depending on the decode we are removing. + for (DUIterator_Fast imax, i = decode->fast_outs(imax); i < imax; i++) { + Node* dependant_lea = decode->fast_out(i); + if (dependant_lea->is_Mach() && dependant_lea->as_Mach()->ideal_Opcode() == Op_AddP) { + dependant_lea->set_req(AddPNode::Base, decode_address); + // This deleted something in the out array, hence adjust i, imax. + --i; + --imax; + } + } + + // Remove spill for the decode if the spill node does not have any other uses. + if (is_spill) { + MachNode* decode_spill = decode->in(1)->as_Mach(); + if (decode_spill->outcnt() == 1 && block->contains(decode_spill)) { + decode_spill->set_removed(); + block->find_remove(decode_spill); + cfg_->map_node_to_block(decode_spill, nullptr); + decode_spill->del_req(1); + } + } + + // Remove the decode + decode->set_removed(); + block->find_remove(decode); + cfg_->map_node_to_block(decode, nullptr); + decode->del_req(1); + + return true; +} + bool Peephole::lea_coalesce_reg(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_, MachNode* (*new_root)(), uint inst0_rule) { return lea_coalesce_helper(block, block_index, cfg_, ra_, new_root, inst0_rule, false); diff --git a/src/hotspot/cpu/x86/peephole_x86_64.hpp b/src/hotspot/cpu/x86/peephole_x86_64.hpp index deb53f0dfd7..954297f555a 100644 --- a/src/hotspot/cpu/x86/peephole_x86_64.hpp +++ b/src/hotspot/cpu/x86/peephole_x86_64.hpp @@ -36,6 +36,8 @@ class Peephole { MachNode* (*new_root)(), uint inst0_rule); static bool test_may_remove(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_, MachNode* (*new_root)(), uint inst0_rule); + static bool lea_remove_redundant(Block* block, int block_index, PhaseCFG* cfg_, PhaseRegAlloc* ra_, + MachNode* (*new_root)(), uint inst0_rule); }; #endif // CPU_X86_PEEPHOLE_X86_64_HPP diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 7b545f0f5f7..3839813c4e3 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -14593,6 +14593,24 @@ peephole peepreplace (leaL_rReg_immI2_peep()); %} +peephole +%{ + peepmatch (leaPCompressedOopOffset); + peepprocedure (lea_remove_redundant); +%} + +peephole +%{ + peepmatch (leaP8Narrow); + peepprocedure (lea_remove_redundant); +%} + +peephole +%{ + peepmatch (leaP32Narrow); + peepprocedure (lea_remove_redundant); +%} + // These peephole rules matches instructions which set flags and are followed by a testI/L_reg // The test instruction is redudanent in case the downstream instuctions (like JCC or CMOV) only use flags that are already set by the previous instruction diff --git a/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java b/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java new file mode 100644 index 00000000000..e58f8660131 --- /dev/null +++ b/test/hotspot/jtreg/compiler/codegen/TestRedundantLea.java @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test id=GetAndSet + * @bug 8020282 + * @summary Test that we do not generate redundant leas on x86 for AtomicReference.getAndSet. + * @requires os.simpleArch == "x64" & vm.opt.TieredCompilation != false + * @modules jdk.compiler/com.sun.tools.javac.util + * @library /test/lib / + * @run driver compiler.codegen.TestRedundantLea GetAndSet + */ + +/* + * @test id=StringEquals + * @bug 8020282 + * @summary Test that we do not generate redundant leas on x86 for String.Equals. + * @requires os.simpleArch == "x64" & vm.opt.TieredCompilation != false + * @modules jdk.compiler/com.sun.tools.javac.util + * @library /test/lib / + * @run driver compiler.codegen.TestRedundantLea StringEquals + */ + +/* + * @test id=StringInflate + * @bug 8020282 + * @summary Test that we do not generate redundant leas on x86 for StringConcat intrinsics. + * @requires os.simpleArch == "x64" & vm.opt.TieredCompilation != false + * @modules jdk.compiler/com.sun.tools.javac.util + * @library /test/lib / + * @run driver compiler.codegen.TestRedundantLea StringInflate + */ + +/* + * @test id=RegexFind + * @bug 8020282 + * @summary Test that we do not generate redundant leas on x86 when performing regex matching. + * @requires os.simpleArch == "x64" & vm.opt.TieredCompilation != false & vm.opt.UseAvx == 3 + * @modules jdk.compiler/com.sun.tools.javac.util + * @library /test/lib / + * @run driver compiler.codegen.TestRedundantLea RegexFind + */ + +/* + * @test id=StoreNSerial + * @bug 8020282 + * @summary Test that we do not generate redundant leas on x86 when storing narrow oops to object arrays. + * @requires os.simpleArch == "x64" & vm.gc.Serial + * @modules jdk.compiler/com.sun.tools.javac.util + * @library /test/lib / + * @run driver compiler.codegen.TestRedundantLea StoreNSerial + */ + +/* + * @test id=StoreNParallel + * @bug 8020282 + * @summary Test that we do not generate redundant leas on x86 when storing narrow oops to object arrays. + * @requires os.simpleArch == "x64" & vm.gc.Parallel + * @modules jdk.compiler/com.sun.tools.javac.util + * @library /test/lib / + * @run driver compiler.codegen.TestRedundantLea StoreNParallel + */ + + +package compiler.codegen; + +import java.util.concurrent.atomic.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import com.sun.tools.javac.util.*; + +import compiler.lib.ir_framework.*; + +// The following tests ensure that we do not generate a redundant lea instruction on x86. +// These get generated on chained dereferences for the rules leaPCompressedOopOffset, +// leaP8Narrow, and leaP32Narrow and stem from a decodeHeapOopNotNull that is not needed +// unless the derived oop is added to an oop map. The redundant lea is removed with an +// opto assembly peephole optimization. Hence, all tests below feature a negative test +// run with -XX:-OptoPeephole to detect changes that obsolete that peephole. +// Further, all tests are run with different max heap sizes to trigger the generation of +// different lea match rules: -XX:MaxHeapSize=32m generates leaP(8|32)Narrow and +// -XX:MaxHeapSize=4g generates leaPCompressedOopOffset, since the address computation +// needs to shift left by 3. +public class TestRedundantLea { + public static void main(String[] args) { + String testName = args[0]; + TestFramework framework; + switch (testName) { + case "GetAndSet" -> { + framework = new TestFramework(GetAndSetTest.class); + } + case "StringEquals" -> { + framework = new TestFramework(StringEqualsTest.class); + framework.addHelperClasses(StringEqualsTestHelper.class); + } + case "StringInflate" -> { + framework = new TestFramework(StringInflateTest.class); + framework.addFlags("--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"); + } + case "RegexFind" -> { + framework = new TestFramework(RegexFindTest.class); + } + case "StoreNSerial" -> { + framework = new TestFramework(StoreNTest.class); + framework.addFlags("-XX:+UseSerialGC"); + } + case "StoreNParallel" -> { + framework = new TestFramework(StoreNTest.class); + framework.addFlags("-XX:+UseParallelGC"); + } + default -> { + throw new IllegalArgumentException("Unknown test name \"" + testName +"\""); + } + } + + Scenario[] scenarios = new Scenario[2]; + // Scenario for the negative test without peephole optimizations. + scenarios[0] = new Scenario(0, "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-OptoPeephole"); + // Scenario for the positive test with +OptoPeephole (the default on x64). + scenarios[1] = new Scenario(1); + framework.addScenarios(scenarios).start(); + } +} + +// This generates a leaP* rule for the chained dereference of obj.value that +// gets passed to the get and set VM intrinsic. +class GetAndSetTest { + private static final Object CURRENT = new Object(); + private final AtomicReference obj = new AtomicReference(); + + @Test + @IR(counts = {IRNode.LEA_P, "=1"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfPlatform = {"mac", "false"}) + // Negative test + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "false"}) + // Test that the peephole worked for leaP(8|32)Narrow + @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "true"}) + public void testGetAndSet() { + obj.getAndSet(CURRENT); + } +} + +// This generates leaP* rules for the chained dereferences of the String.value +// fields that are used in the string_equals VM intrinsic. +class StringEqualsTest { + final StringEqualsTestHelper strEqHelper = new StringEqualsTestHelper("I am the string that is tested against"); + + @Setup + private static Object[] setup() { + return new Object[]{"I will be compared!"}; + } + + @Test + @IR(counts = {IRNode.LEA_P, "=2"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfPlatform = {"mac", "false"}) + // Negative test + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=3"}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "false"}) + // Test that the peephole worked for leaPCompressedOopOffset + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "true"}) + @Arguments(setup = "setup") + public boolean test(String str) { + return strEqHelper.doEquals(str); + } +} + +class StringEqualsTestHelper { + private String str; + + public StringEqualsTestHelper(String str) { + this.str = str; + } + + @ForceInline + public boolean doEquals(String other) { + return this.str.equals(other); + } +} + +// With all VM instrinsics disabled, this test only generates a leaP* rule +// before the string_inflate intrinsic (with -XX:-OptimizeStringConcat no +// leaP* rule is generated). With VM intrinsics enabled (this is the case +// here) leaP* rules are also generated for the string_equals and arrays_hashcode +// VM instrinsics. +// This generates a larger number of decodes for -XX:UseAVX={0,1} than for +// other flags. +class StringInflateTest { + @Setup + private static Object[] setup() { + Names names = new Names(new Context()); + Name n1 = names.fromString("one"); + Name n2 = names.fromString("two"); + return new Object[] {n1, n2}; + } + + @Test + @IR(counts = {IRNode.LEA_P, "=2"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfPlatform = {"mac", "false"}) + // Negative + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=5"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfAnd = {"OptoPeephole", "false", "UseAVX", ">=2"}) + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=13"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfAnd = {"OptoPeephole", "false", "UseAVX", "<2"}) + // 2 decodes get removed + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=3"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfAnd = {"OptoPeephole", "true", "UseAVX", ">=2"}) + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=11"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfAnd = {"OptoPeephole", "true", "UseAVX", "<2"}) + @Arguments(setup = "setup") + public static Name test(Name n1, Name n2) { + return n1.append(n2); + } +} + +// This test case generates leaP* rules before arrayof_jint_fill intrinsics, +// but only with -XX:+UseAVX3. +class RegexFindTest { + @Setup + private static Object[] setup() { + Pattern pat = Pattern.compile("27"); + Matcher m = pat.matcher(" 274 leaPCompressedOopOffset === _ 275 277 [[ 2246 165 294 ]] #16/0x0000000000000010byte[int:>=0]"); + return new Object[] { m }; + } + + @Test + @IR(counts = {IRNode.LEA_P, "=1"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfPlatform = {"mac", "false"}) + // Due to unpredictable code generation, we cannot match the exact number of decodes below. + // Negative test + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, ">=7"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfAnd = {"OptoPeephole", "false", "UseAVX", "=3"}) + // Test that the peephole worked for leaPCompressedOopOffset + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, ">=6"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfAnd = {"OptoPeephole", "true", "UseAVX", "=3"}) + @Arguments(setup = "setup") + public boolean test(Matcher m) { + return m.find(); + } +} + +// The matcher generates leaP* rules for storing an object in an array of objects +// at a constant offset, but only when using the Serial or Parallel GC. +// Here, we can also manipulate the offset such that we get a leaP32Narrow rule +// and we can demonstrate that the peephole also removes simple cases of unneeded +// spills. +class StoreNTest { + private static final int SOME_SIZE = 42; + private static final int OFFSET8BIT_IDX = 3; + private static final int OFFSET32BIT_IDX = 33; + + private static final Object CURRENT = new Object(); + private static final Object OTHER = new Object(); + + private StoreNTestHelper[] classArr8bit = new StoreNTestHelper[SOME_SIZE]; + private StoreNTestHelper[] classArr32bit = new StoreNTestHelper[SOME_SIZE]; + private Object[] objArr8bit = new Object[SOME_SIZE]; + private Object[] objArr32bit = new Object[SOME_SIZE]; + + @Test + @IR(counts = {IRNode.LEA_P, "=2"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfPlatform = {"mac", "false"}) + // Negative test + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=2"}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "false"}) + // Test that the peephole worked for leaPCompressedOopOffset + @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "true"}) + // Test that the peephole removes a spill. + @IR(counts = {IRNode.MEM_TO_REG_SPILL_COPY, "=4"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfAnd ={"OptoPeephole", "false", "UseCompactObjectHeaders", "false"}) + @IR(counts = {IRNode.MEM_TO_REG_SPILL_COPY, "=3"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfAnd ={"OptoPeephole", "true", "UseCompactObjectHeaders", "false"}) + public void testRemoveSpill() { + this.classArr8bit[OFFSET8BIT_IDX] = new StoreNTestHelper(CURRENT, OTHER); + this.classArr32bit[OFFSET32BIT_IDX] = new StoreNTestHelper(OTHER, CURRENT); + } + + // This variation of the test above generates a split spill register path. + // Due to the complicated graph structure with the phis, the peephole + // cannot remove the redundant decode shared by both leaP*s. + @Test + @IR(counts = {IRNode.LEA_P, "=2"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfPlatform = {"mac", "false"}) + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "false"}) + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "true"}) + public void testPhiSpill() { + this.classArr8bit[OFFSET8BIT_IDX] = new StoreNTestHelper(CURRENT, OTHER); + this.classArr8bit[OFFSET32BIT_IDX] = new StoreNTestHelper(CURRENT, OTHER); + } + + @Test + @IR(counts = {IRNode.LEA_P, "=2"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfPlatform = {"mac", "false"}) + // Negative test + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=2"}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "false"}) + // Test that the peephole worked for leaPCompressedOopOffset + @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "true"}) + public void testNoAlloc() { + this.objArr8bit[OFFSET8BIT_IDX] = CURRENT; + this.objArr32bit[OFFSET32BIT_IDX] = OTHER; + } + + @Test + @IR(counts = {IRNode.LEA_P, "=2"}, + phase = {CompilePhase.FINAL_CODE}, + applyIfPlatform = {"mac", "false"}) + // Negative test + @IR(counts = {IRNode.DECODE_HEAP_OOP_NOT_NULL, "=1"}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "false"}) + // Test that the peephole worked for leaPCompressedOopOffset + @IR(failOn = {IRNode.DECODE_HEAP_OOP_NOT_NULL}, + phase = {CompilePhase.FINAL_CODE}, + applyIf = {"OptoPeephole", "true"}) + public void testNoAllocSameArray() { + this.objArr8bit[OFFSET8BIT_IDX] = CURRENT; + this.objArr8bit[OFFSET32BIT_IDX] = OTHER; + } +} + +class StoreNTestHelper { + Object o1; + Object o2; + + public StoreNTestHelper(Object o1, Object o2) { + this.o1 = o1; + this.o2 = o2; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 9388e1a8892..e7582015e86 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -649,6 +649,11 @@ public class IRNode { fromAfterCountedLoops(COUNTED_LOOP_MAIN, regex); } + public static final String DECODE_HEAP_OOP_NOT_NULL = PREFIX + "DECODE_HEAP_OOP_NOT_NULL" + POSTFIX; + static { + machOnly(DECODE_HEAP_OOP_NOT_NULL, "decodeHeapOop_not_null"); + } + public static final String DIV = PREFIX + "DIV" + POSTFIX; static { beforeMatchingNameRegex(DIV, "Div(I|L|F|D)"); @@ -870,6 +875,12 @@ public class IRNode { beforeMatchingNameRegex(IS_INFINITE_F, "IsInfiniteF"); } + // Only supported on x86. + public static final String LEA_P = PREFIX + "LEA_P" + POSTFIX; + static { + machOnly(LEA_P, "leaP(CompressedOopOffset|(8|32)Narrow)"); + } + public static final String LOAD = PREFIX + "LOAD" + POSTFIX; static { beforeMatchingNameRegex(LOAD, "Load(B|UB|S|US|I|L|F|D|P|N)"); @@ -1208,6 +1219,11 @@ public class IRNode { beforeMatchingNameRegex(MEMBAR_VOLATILE, "MemBarVolatile"); } + public static final String MEM_TO_REG_SPILL_COPY = PREFIX + "MEM_TO_REG_SPILL_COPY" + POSTFIX; + static { + machOnly(MEM_TO_REG_SPILL_COPY, "MemToRegSpillCopy"); + } + public static final String MIN = PREFIX + "MIN" + POSTFIX; static { beforeMatchingNameRegex(MIN, "Min(I|L)"); diff --git a/test/micro/org/openjdk/bench/vm/compiler/x86/RedundantLeaPeephole.java b/test/micro/org/openjdk/bench/vm/compiler/x86/RedundantLeaPeephole.java new file mode 100644 index 00000000000..00a33a47617 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/x86/RedundantLeaPeephole.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.vm.compiler.x86; + +import org.openjdk.jmh.annotations.*; + +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Warmup(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS) +@Measurement(iterations = 10, time = 1, timeUnit = TimeUnit.SECONDS) +// Fix heap size since the StoreN benchmarks are allocating a lot and dependent on GC selection and compressed oop mode. +@Fork(value = 3, jvmArgsAppend = {"-Xms1g", "-Xmx1g"}) +@State(Scope.Thread) +public class RedundantLeaPeephole { + @State(Scope.Thread) + public class StoreNHelper { + Object o1; + Object o2; + + public StoreNHelper(Object o1, Object o2) { + this.o1 = o1; + this.o2 = o2; + } + } + + @State(Scope.Thread) + public class StringEqualsHelper { + private String str; + + public StringEqualsHelper(String str) { + this.str = str; + } + + @CompilerControl(CompilerControl.Mode.INLINE) + public boolean doEquals(String other) { + return this.str.equals(other); + } + } + + private static final int SIZE = 42; + private static final int SMALL_IDX = 3; + private static final int BIG_IDX = 33; + + private static final Object O1 = new Object(); + private static final Object O2 = new Object(); + + private Object[] arr1 = new Object[SIZE]; + private Object[] arr2 = new Object[SIZE]; + private StoreNHelper[] arrH1 = new StoreNHelper[SIZE]; + private StoreNHelper[] arrH2 = new StoreNHelper[SIZE]; + + private StringEqualsHelper strEqHelper = new StringEqualsHelper("foo"); + + @Benchmark + @Fork(jvmArgsAppend = {"-XX:+UseSerialGC"}) + public void benchStoreNRemoveSpillSerial() { + this.arrH1[SMALL_IDX] = new StoreNHelper(O1, O2); + this.arrH2[BIG_IDX] = new StoreNHelper(O2, O1); + } + + @Benchmark + @Fork(jvmArgsAppend = {"-XX:+UseParallelGC"}) + public void benchStoreNRemoveSpillParallel() { + this.arrH1[SMALL_IDX] = new StoreNHelper(O1, O2); + this.arrH2[BIG_IDX] = new StoreNHelper(O2, O1); + } + + @Benchmark + @Fork(jvmArgsAppend = {"-XX:+UseSerialGC"}) + public void benchStoreNNoAllocSerial() { + this.arr1[SMALL_IDX] = O1; + this.arr1[BIG_IDX] = O2; + this.arr2[SMALL_IDX] = O1; + this.arr2[BIG_IDX] = O2; + } + + @Benchmark + @Fork(jvmArgsAppend = {"-XX:+UseParallelGC"}) + public void benchStoreNNoAllocParallel() { + this.arr1[SMALL_IDX] = O1; + this.arr1[BIG_IDX] = O2; + this.arr2[SMALL_IDX] = O1; + this.arr2[BIG_IDX] = O2; + } + + @Benchmark + public boolean benchStringEquals() { + return this.strEqHelper.doEquals("bar"); + } +} From 01d4b772dee8470188793676ce983d6203c7fefb Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Thu, 19 Jun 2025 10:20:49 +0000 Subject: [PATCH 112/213] 8319242: HotSpot Style Guide should discourage non-local variables with non-trivial initialization or destruction Reviewed-by: stefank, dcubed, dholmes --- doc/hotspot-style.html | 36 ++++++++++++++++++++++++++++++------ doc/hotspot-style.md | 33 ++++++++++++++++++++++++++------- 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/doc/hotspot-style.html b/doc/hotspot-style.html index d4c06fbd6bd..22fd7b8167b 100644 --- a/doc/hotspot-style.html +++ b/doc/hotspot-style.html @@ -77,6 +77,9 @@

    HotSpot Coding Style

  • thread_local
  • nullptr
  • <atomic>
  • +
  • Initializing +variables with static storage duration
  • Uniform Initialization
  • <atomic> "conservative" memory ordering, which may differ from (may be stronger than) sequentially consistent. There are algorithms in HotSpot that are believed to rely on that ordering.

    +

    Initializing +variables with static storage duration

    +

    Variables with static storage duration and dynamic +initialization C++14 +3.6.2). should be avoided, unless an implementation is permitted to +perform the initialization as a static initialization. The order in +which dynamic initializations occur is incompletely specified. +Initialization order problems can be difficult to deal with and lead to +surprises.

    +

    Variables with static storage duration and non-trivial destructors +should be avoided. HotSpot doesn't generally try to cleanup on exit, and +running destructors at exit can lead to problems.

    +

    Some of the approaches used in HotSpot to avoid dynamic +initialization include:

    +
      +
    • Use the Deferred<T> class template. Add a call +to its initialization function at an appropriate place during VM +initialization. The underlying object is never destroyed.

    • +
    • For objects of class type, use a variable whose value is a +pointer to the class, initialized to nullptr. Provide an +initialization function that sets the variable to a dynamically +allocated object. Add a call to that function at an appropriate place +during VM initialization. Such objects are usually never +destroyed.

    • +

    Uniform Initialization

    The use of uniform initialization (n2672), @@ -1198,12 +1228,6 @@

    Excluded Features

    href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html">n2179) — HotSpot does not permit the use of exceptions, so this feature isn't useful.

  • -
  • Avoid non-local variables with non-constexpr initialization. In -particular, avoid variables with types requiring non-trivial -initialization or destruction. Initialization order problems can be -difficult to deal with and lead to surprises, as can destruction -ordering. HotSpot doesn't generally try to cleanup on exit, and running -destructors at exit can also lead to problems.

  • Avoid most operator overloading, preferring named functions. When operator overloading is used, ensure the semantics conform to the normal expected behavior of the operation.

  • diff --git a/doc/hotspot-style.md b/doc/hotspot-style.md index f4348bea51d..92b756e10d3 100644 --- a/doc/hotspot-style.md +++ b/doc/hotspot-style.md @@ -770,6 +770,32 @@ ordering, which may differ from (may be stronger than) sequentially consistent. There are algorithms in HotSpot that are believed to rely on that ordering. +### Initializing variables with static storage duration + +Variables with static storage duration and _dynamic initialization_ +[C++14 3.6.2](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)). +should be avoided, unless an implementation is permitted to perform the +initialization as a static initialization. The order in which dynamic +initializations occur is incompletely specified. Initialization order +problems can be difficult to deal with and lead to surprises. + +Variables with static storage duration and non-trivial destructors should be +avoided. HotSpot doesn't generally try to cleanup on exit, and running +destructors at exit can lead to problems. + +Some of the approaches used in HotSpot to avoid dynamic initialization +include: + +* Use the `Deferred` class template. Add a call to its initialization +function at an appropriate place during VM initialization. The underlying +object is never destroyed. + +* For objects of class type, use a variable whose value is a pointer to the +class, initialized to `nullptr`. Provide an initialization function that sets +the variable to a dynamically allocated object. Add a call to that function at +an appropriate place during VM initialization. Such objects are usually never +destroyed. + ### Uniform Initialization The use of _uniform initialization_ @@ -1199,13 +1225,6 @@ namespace std;` to avoid needing to qualify Standard Library names. ([n2179](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2179.html)) — HotSpot does not permit the use of exceptions, so this feature isn't useful. -* Avoid non-local variables with non-constexpr initialization. -In particular, avoid variables with types requiring non-trivial -initialization or destruction. Initialization order problems can be -difficult to deal with and lead to surprises, as can destruction -ordering. HotSpot doesn't generally try to cleanup on exit, and -running destructors at exit can also lead to problems. - * Avoid most operator overloading, preferring named functions. When operator overloading is used, ensure the semantics conform to the normal expected behavior of the operation. From c4fb00a7be51c7a05a29d3d57d787feb5c698ddf Mon Sep 17 00:00:00 2001 From: Nizar Benalla Date: Thu, 19 Jun 2025 10:38:24 +0000 Subject: [PATCH 113/213] 8358769: Update --release 25 symbol information for JDK 25 build 26 Reviewed-by: darcy, iris --- .../share/data/symbols/java.base-P.sym.txt | 89 +++++++++++++++++++ .../share/data/symbols/java.desktop-P.sym.txt | 12 +++ .../symbols/jdk.incubator.vector-P.sym.txt | 1 + .../share/data/symbols/jdk.jfr-P.sym.txt | 8 ++ 4 files changed, 110 insertions(+) diff --git a/src/jdk.compiler/share/data/symbols/java.base-P.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-P.sym.txt index 95544fc3cac..36f9e40e526 100644 --- a/src/jdk.compiler/share/data/symbols/java.base-P.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.base-P.sym.txt @@ -51,6 +51,10 @@ class name java/io/ProxyingConsole -method name readln descriptor (Ljava/lang/String;)Ljava/lang/String; -method name readln descriptor ()Ljava/lang/String; +class name java/io/Reader +method name readAllLines descriptor ()Ljava/util/List; thrownTypes java/io/IOException flags 1 signature ()Ljava/util/List; +method name readAllAsString descriptor ()Ljava/lang/String; thrownTypes java/io/IOException flags 1 + class name java/io/SerializablePermission header extends java/security/BasicPermission flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="25") @@ -118,6 +122,7 @@ method name descriptor (J)V flags 1 deprecated true runtimeAnnotations @L method name descriptor (Ljava/lang/String;)V thrownTypes java/lang/NumberFormatException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") class name java/lang/Math +-method name cbrt descriptor (D)D -method name max descriptor (JJ)J -method name min descriptor (JJ)J method name max descriptor (JJ)J flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; @@ -129,6 +134,7 @@ method name powExact descriptor (II)I flags 9 method name unsignedPowExact descriptor (II)I flags 9 method name powExact descriptor (JI)J flags 9 method name unsignedPowExact descriptor (JI)J flags 9 +method name cbrt descriptor (D)D flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; class name java/lang/Package header extends java/lang/NamedPackage implements java/lang/reflect/AnnotatedElement flags 31 @@ -145,6 +151,20 @@ innerclass innerClass java/lang/Runtime$Version outerClass java/lang/Runtime inn class name java/lang/RuntimePermission header extends java/security/BasicPermission flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="25") +class name java/lang/ScopedValue +header extends java/lang/Object nestMembers java/lang/ScopedValue$CallableOp,java/lang/ScopedValue$Carrier flags 31 signature Ljava/lang/Object; +innerclass innerClass java/lang/ScopedValue$Carrier outerClass java/lang/ScopedValue innerClassName Carrier flags 19 +innerclass innerClass java/lang/ScopedValue$CallableOp outerClass java/lang/ScopedValue innerClassName CallableOp flags 609 + +class name java/lang/ScopedValue$CallableOp +header extends java/lang/Object nestHost java/lang/ScopedValue flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/ScopedValue$CallableOp outerClass java/lang/ScopedValue innerClassName CallableOp flags 609 + +class name java/lang/ScopedValue$Carrier +header extends java/lang/Object nestHost java/lang/ScopedValue flags 31 +innerclass innerClass java/lang/ScopedValue$Carrier outerClass java/lang/ScopedValue innerClassName Carrier flags 19 +innerclass innerClass java/lang/ScopedValue$CallableOp outerClass java/lang/ScopedValue innerClassName CallableOp flags 609 + class name java/lang/Short -method name descriptor (S)V -method name descriptor (Ljava/lang/String;)V @@ -426,6 +446,12 @@ header extends java/lang/Object flags 31 class name java/nio/file/LinkPermission header extends java/security/BasicPermission flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="25") +class name java/security/AsymmetricKey +header extends java/lang/Object implements java/security/Key,java/security/DEREncodable flags 601 + +class name java/security/DEREncodable +header extends java/lang/Object sealed true permittedSubclasses java/security/AsymmetricKey,java/security/KeyPair,java/security/spec/PKCS8EncodedKeySpec,java/security/spec/X509EncodedKeySpec,javax/crypto/EncryptedPrivateKeyInfo,java/security/cert/X509Certificate,java/security/cert/X509CRL,java/security/PEMRecord flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) + class name java/security/DrbgParameters header extends java/lang/Object nestMembers java/security/DrbgParameters$Reseed,java/security/DrbgParameters$NextBytes,java/security/DrbgParameters$Instantiation,java/security/DrbgParameters$Capability flags 31 innerclass innerClass java/security/DrbgParameters$Instantiation outerClass java/security/DrbgParameters innerClassName Instantiation flags 19 @@ -433,12 +459,63 @@ innerclass innerClass java/security/DrbgParameters$Capability outerClass java/se innerclass innerClass java/security/DrbgParameters$NextBytes outerClass java/security/DrbgParameters innerClassName NextBytes flags 19 innerclass innerClass java/security/DrbgParameters$Reseed outerClass java/security/DrbgParameters innerClassName Reseed flags 19 +class name java/security/KeyPair +header extends java/lang/Object implements java/io/Serializable,java/security/DEREncodable flags 31 + +class name java/security/PEMDecoder +header extends java/lang/Object flags 31 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +innerclass innerClass java/util/Base64$Decoder outerClass java/util/Base64 innerClassName Decoder flags 9 +method name of descriptor ()Ljava/security/PEMDecoder; flags 9 +method name decode descriptor (Ljava/lang/String;)Ljava/security/DEREncodable; flags 1 +method name decode descriptor (Ljava/io/InputStream;)Ljava/security/DEREncodable; thrownTypes java/io/IOException flags 1 +method name decode descriptor (Ljava/lang/String;Ljava/lang/Class;)Ljava/security/DEREncodable; flags 1 signature (Ljava/lang/String;Ljava/lang/Class;)TS; +method name decode descriptor (Ljava/io/InputStream;Ljava/lang/Class;)Ljava/security/DEREncodable; thrownTypes java/io/IOException flags 1 signature (Ljava/io/InputStream;Ljava/lang/Class;)TS; +method name withFactory descriptor (Ljava/security/Provider;)Ljava/security/PEMDecoder; flags 1 +method name withDecryption descriptor ([C)Ljava/security/PEMDecoder; flags 1 + +class name java/security/PEMEncoder +header extends java/lang/Object flags 31 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name of descriptor ()Ljava/security/PEMEncoder; flags 9 +method name encodeToString descriptor (Ljava/security/DEREncodable;)Ljava/lang/String; flags 1 +method name encode descriptor (Ljava/security/DEREncodable;)[B flags 1 +method name withEncryption descriptor ([C)Ljava/security/PEMEncoder; flags 1 + +class name java/security/PEMRecord +header extends java/lang/Record implements java/security/DEREncodable record true flags 31 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +recordcomponent name type descriptor Ljava/lang/String; +recordcomponent name pem descriptor Ljava/lang/String; +recordcomponent name leadingData descriptor [B +innerclass innerClass java/util/Base64$Decoder outerClass java/util/Base64 innerClassName Decoder flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name descriptor (Ljava/lang/String;Ljava/lang/String;[B)V flags 1 methodParameters 0:type,0:pem,0:leadingData +method name descriptor (Ljava/lang/String;Ljava/lang/String;)V flags 1 +method name getEncoded descriptor ()[B flags 1 +method name toString descriptor ()Ljava/lang/String; flags 1 +method name hashCode descriptor ()I flags 11 +method name equals descriptor (Ljava/lang/Object;)Z flags 11 +method name type descriptor ()Ljava/lang/String; flags 1 +method name pem descriptor ()Ljava/lang/String; flags 1 +method name leadingData descriptor ()[B flags 1 + class name java/security/SecurityPermission header extends java/security/BasicPermission flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="25") class name java/security/UnresolvedPermission header extends java/security/Permission implements java/io/Serializable flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="25") +class name java/security/cert/X509CRL +header extends java/security/cert/CRL implements java/security/cert/X509Extension,java/security/DEREncodable flags 421 + +class name java/security/cert/X509Certificate +header extends java/security/cert/Certificate implements java/security/cert/X509Extension,java/security/DEREncodable flags 421 + +class name java/security/spec/PKCS8EncodedKeySpec +header extends java/security/spec/EncodedKeySpec implements java/security/DEREncodable flags 21 + +class name java/security/spec/X509EncodedKeySpec +header extends java/security/spec/EncodedKeySpec implements java/security/DEREncodable flags 21 + class name java/time/ZoneOffset header extends java/time/ZoneId implements java/time/temporal/TemporalAccessor,java/time/temporal/TemporalAdjuster,java/lang/Comparable,java/io/Serializable flags 31 signature Ljava/time/ZoneId;Ljava/time/temporal/TemporalAccessor;Ljava/time/temporal/TemporalAdjuster;Ljava/lang/Comparable;Ljava/io/Serializable; runtimeAnnotations @Ljdk/internal/ValueBased; @@ -641,6 +718,14 @@ class name java/util/zip/Inflater header extends java/lang/Object implements java/lang/AutoCloseable flags 21 method name close descriptor ()V flags 1 +class name javax/crypto/EncryptedPrivateKeyInfo +header extends java/lang/Object implements java/security/DEREncodable flags 21 +method name encryptKey descriptor (Ljava/security/PrivateKey;[CLjava/lang/String;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/Provider;)Ljavax/crypto/EncryptedPrivateKeyInfo; flags 9 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +method name encryptKey descriptor (Ljava/security/PrivateKey;[C)Ljavax/crypto/EncryptedPrivateKeyInfo; flags 9 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +method name encryptKey descriptor (Ljava/security/PrivateKey;Ljava/security/Key;Ljava/lang/String;Ljava/security/spec/AlgorithmParameterSpec;Ljava/security/Provider;Ljava/security/SecureRandom;)Ljavax/crypto/EncryptedPrivateKeyInfo; flags 9 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +method name getKey descriptor ([C)Ljava/security/PrivateKey; thrownTypes java/security/GeneralSecurityException flags 1 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +method name getKey descriptor (Ljava/security/Key;Ljava/security/Provider;)Ljava/security/PrivateKey; thrownTypes java/security/GeneralSecurityException flags 1 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) + class name javax/crypto/KDF header extends java/lang/Object flags 31 innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 @@ -678,6 +763,10 @@ innerclass innerClass javax/crypto/spec/HKDFParameterSpec$ExtractThenExpand oute innerclass innerClass javax/crypto/spec/HKDFParameterSpec$Extract outerClass javax/crypto/spec/HKDFParameterSpec innerClassName Extract flags 19 innerclass innerClass javax/crypto/spec/HKDFParameterSpec$Expand outerClass javax/crypto/spec/HKDFParameterSpec innerClassName Expand flags 19 +class name javax/net/ssl/ExtendedSSLSession +method name exportKeyingMaterialKey descriptor (Ljava/lang/String;Ljava/lang/String;[BI)Ljavax/crypto/SecretKey; thrownTypes javax/net/ssl/SSLKeyException flags 1 +method name exportKeyingMaterialData descriptor (Ljava/lang/String;[BI)[B thrownTypes javax/net/ssl/SSLKeyException flags 1 + class name javax/net/ssl/SSLPermission header extends java/security/BasicPermission flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="25") diff --git a/src/jdk.compiler/share/data/symbols/java.desktop-P.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-P.sym.txt index 23b567b6c05..4a3684710e7 100644 --- a/src/jdk.compiler/share/data/symbols/java.desktop-P.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.desktop-P.sym.txt @@ -26,10 +26,22 @@ # ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### # ########################################################## # +module name java.desktop +header exports java/applet,java/awt,java/awt/color,java/awt/desktop,java/awt/dnd,java/awt/event,java/awt/font,java/awt/geom,java/awt/im,java/awt/im/spi,java/awt/image,java/awt/image/renderable,java/awt/print,java/beans,java/beans/beancontext,javax/accessibility,javax/imageio,javax/imageio/event,javax/imageio/metadata,javax/imageio/plugins/bmp,javax/imageio/plugins/jpeg,javax/imageio/plugins/tiff,javax/imageio/spi,javax/imageio/stream,javax/print,javax/print/attribute,javax/print/attribute/standard,javax/print/event,javax/sound,javax/sound/midi,javax/sound/midi/spi,javax/sound/sampled,javax/sound/sampled/spi,javax/swing,javax/swing/border,javax/swing/colorchooser,javax/swing/event,javax/swing/filechooser,javax/swing/plaf,javax/swing/plaf/basic,javax/swing/plaf/metal,javax/swing/plaf/multi,javax/swing/plaf/nimbus,javax/swing/plaf/synth,javax/swing/table,javax/swing/text,javax/swing/text/html,javax/swing/text/html/parser,javax/swing/text/rtf,javax/swing/tree,javax/swing/undo extraModulePackages sun/print requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;java.prefs\u0020;flags\u0020;0,name\u0020;java.datatransfer\u0020;flags\u0020;20,name\u0020;java.xml\u0020;flags\u0020;20 uses java/awt/im/spi/InputMethodDescriptor,javax/accessibility/AccessibilityProvider,javax/imageio/spi/ImageInputStreamSpi,javax/imageio/spi/ImageOutputStreamSpi,javax/imageio/spi/ImageReaderSpi,javax/imageio/spi/ImageTranscoderSpi,javax/imageio/spi/ImageWriterSpi,javax/print/PrintServiceLookup,javax/print/StreamPrintServiceFactory,javax/sound/midi/spi/MidiDeviceProvider,javax/sound/midi/spi/MidiFileReader,javax/sound/midi/spi/MidiFileWriter,javax/sound/midi/spi/SoundbankReader,javax/sound/sampled/spi/AudioFileReader,javax/sound/sampled/spi/AudioFileWriter,javax/sound/sampled/spi/FormatConversionProvider,javax/sound/sampled/spi/MixerProvider,sun/swing/InteropProvider provides interface\u0020;sun/datatransfer/DesktopDatatransferService\u0020;impls\u0020;sun/awt/datatransfer/DesktopDatatransferServiceImpl,interface\u0020;java/net/ContentHandlerFactory\u0020;impls\u0020;sun/awt/www/content/MultimediaContentHandlers,interface\u0020;javax/print/PrintServiceLookup\u0020;impls\u0020;sun/print/PrintServiceLookupProvider,interface\u0020;javax/print/StreamPrintServiceFactory\u0020;impls\u0020;sun/print/PSStreamPrinterFactory,interface\u0020;javax/sound/midi/spi/MidiDeviceProvider\u0020;impls\u0020;com/sun/media/sound/MidiInDeviceProvider\u005C;u002C;com/sun/media/sound/MidiOutDeviceProvider\u005C;u002C;com/sun/media/sound/RealTimeSequencerProvider\u005C;u002C;com/sun/media/sound/SoftProvider,interface\u0020;javax/sound/midi/spi/MidiFileReader\u0020;impls\u0020;com/sun/media/sound/StandardMidiFileReader,interface\u0020;javax/sound/midi/spi/MidiFileWriter\u0020;impls\u0020;com/sun/media/sound/StandardMidiFileWriter,interface\u0020;javax/sound/midi/spi/SoundbankReader\u0020;impls\u0020;com/sun/media/sound/AudioFileSoundbankReader\u005C;u002C;com/sun/media/sound/DLSSoundbankReader\u005C;u002C;com/sun/media/sound/JARSoundbankReader\u005C;u002C;com/sun/media/sound/SF2SoundbankReader,interface\u0020;javax/sound/sampled/spi/AudioFileReader\u0020;impls\u0020;com/sun/media/sound/AiffFileReader\u005C;u002C;com/sun/media/sound/AuFileReader\u005C;u002C;com/sun/media/sound/SoftMidiAudioFileReader\u005C;u002C;com/sun/media/sound/WaveFileReader\u005C;u002C;com/sun/media/sound/WaveFloatFileReader\u005C;u002C;com/sun/media/sound/WaveExtensibleFileReader,interface\u0020;javax/sound/sampled/spi/AudioFileWriter\u0020;impls\u0020;com/sun/media/sound/AiffFileWriter\u005C;u002C;com/sun/media/sound/AuFileWriter\u005C;u002C;com/sun/media/sound/WaveFileWriter\u005C;u002C;com/sun/media/sound/WaveFloatFileWriter,interface\u0020;javax/sound/sampled/spi/FormatConversionProvider\u0020;impls\u0020;com/sun/media/sound/AlawCodec\u005C;u002C;com/sun/media/sound/AudioFloatFormatConverter\u005C;u002C;com/sun/media/sound/PCMtoPCMCodec\u005C;u002C;com/sun/media/sound/UlawCodec,interface\u0020;javax/sound/sampled/spi/MixerProvider\u0020;impls\u0020;com/sun/media/sound/DirectAudioDeviceProvider\u005C;u002C;com/sun/media/sound/PortMixerProvider target macos-aarch64 flags 8000 + class name java/awt/Color -method name createContext descriptor (Ljava/awt/image/ColorModel;Ljava/awt/Rectangle;Ljava/awt/geom/Rectangle2D;Ljava/awt/geom/AffineTransform;Ljava/awt/RenderingHints;)Ljava/awt/PaintContext; method name createContext descriptor (Ljava/awt/image/ColorModel;Ljava/awt/Rectangle;Ljava/awt/geom/Rectangle2D;Ljava/awt/geom/AffineTransform;Ljava/awt/RenderingHints;)Ljava/awt/PaintContext; flags 1 +class name javax/sound/SoundClip +header extends java/lang/Object flags 31 +method name createSoundClip descriptor (Ljava/io/File;)Ljavax/sound/SoundClip; thrownTypes java/io/IOException flags 9 +method name canPlay descriptor ()Z flags 1 +method name isPlaying descriptor ()Z flags 1 +method name play descriptor ()V flags 1 +method name loop descriptor ()V flags 1 +method name stop descriptor ()V flags 1 + class name javax/swing/plaf/basic/BasicScrollBarUI$ScrollListener header extends java/lang/Object implements java/awt/event/ActionListener nestHost javax/swing/plaf/basic/BasicScrollBarUI flags 21 innerclass innerClass javax/swing/plaf/basic/BasicScrollBarUI$ScrollListener outerClass javax/swing/plaf/basic/BasicScrollBarUI innerClassName ScrollListener flags 4 diff --git a/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-P.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-P.sym.txt index cae81b02a3d..7f6a2e0bcfa 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-P.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-P.sym.txt @@ -90,6 +90,7 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang class name jdk/incubator/vector/VectorShape -method name forBitSize descriptor (I)Ljdk/incubator/vector/VectorShape; method name forBitSize descriptor (I)Ljdk/incubator/vector/VectorShape; flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name largestShapeFor descriptor (Ljava/lang/Class;)Ljdk/incubator/vector/VectorShape; flags 9 signature (Ljava/lang/Class<*>;)Ljdk/incubator/vector/VectorShape; class name jdk/incubator/vector/VectorShuffle header extends jdk/internal/vm/vector/VectorSupport$VectorShuffle flags 421 signature Ljdk/internal/vm/vector/VectorSupport$VectorShuffle; diff --git a/src/jdk.compiler/share/data/symbols/jdk.jfr-P.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jfr-P.sym.txt index 8f7fe9f5699..4325289f570 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.jfr-P.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.jfr-P.sym.txt @@ -26,6 +26,14 @@ # ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### # ########################################################## # +class name jdk/jfr/Contextual +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljdk/jfr/MetadataDefinition;@Ljdk/jfr/Label;(value="Context")@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;)@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;FIELD;}) + class name jdk/jfr/FlightRecorderPermission header extends java/security/BasicPermission flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="25") +class name jdk/jfr/Throttle +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljdk/jfr/MetadataDefinition;@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;TYPE;})@Ljava/lang/annotation/Inherited;@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;) +field name NAME descriptor Ljava/lang/String; constantValue throttle flags 19 +method name value descriptor ()Ljava/lang/String; annotationDefaultValue "off" flags 401 + From 2e3bdec9857c64b307737ac7afed58170125cca9 Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Thu, 19 Jun 2025 15:49:49 +0000 Subject: [PATCH 114/213] 8358686: CDS and AOT can cause buffer truncation warning even when logging is disabled Reviewed-by: dnsimon, iklam --- src/hotspot/share/cds/metaspaceShared.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index 02f53feeed8..6c6b64a0cb2 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -1288,6 +1288,10 @@ void MetaspaceShared::report_loading_error(const char* format, ...) { LogStream ls_cds(level, LogTagSetMapping::tagset()); LogStream& ls = CDSConfig::new_aot_flags_used() ? ls_aot : ls_cds; + if (!ls.is_enabled()) { + return; + } + va_list ap; va_start(ap, format); From 2fe12984474656a08c4525c04a351d85be73f658 Mon Sep 17 00:00:00 2001 From: Cesar Soares Lucas Date: Thu, 19 Jun 2025 18:02:41 +0000 Subject: [PATCH 115/213] 8359064: Expose reason for marking nmethod non-entrant to JVMCI client Reviewed-by: dnsimon, never --- src/hotspot/share/c1/c1_Runtime1.cpp | 8 +- src/hotspot/share/ci/ciReplay.cpp | 2 +- src/hotspot/share/code/codeCache.cpp | 2 +- src/hotspot/share/code/nmethod.cpp | 16 +-- src/hotspot/share/code/nmethod.hpp | 107 +++++++++--------- .../share/compiler/compilationPolicy.cpp | 4 +- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 26 ++++- src/hotspot/share/jvmci/jvmciEnv.cpp | 6 +- src/hotspot/share/jvmci/jvmciEnv.hpp | 2 +- src/hotspot/share/jvmci/jvmciJavaClasses.hpp | 1 + src/hotspot/share/jvmci/jvmciRuntime.cpp | 12 +- src/hotspot/share/jvmci/jvmciRuntime.hpp | 2 +- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 25 +++- src/hotspot/share/oops/instanceKlass.cpp | 2 +- src/hotspot/share/oops/method.cpp | 2 +- src/hotspot/share/prims/whitebox.cpp | 2 +- src/hotspot/share/runtime/deoptimization.cpp | 4 +- src/hotspot/share/runtime/javaThread.cpp | 2 +- .../jdk/vm/ci/hotspot/CompilerToVM.java | 4 +- .../ci/hotspot/HotSpotCodeCacheProvider.java | 14 ++- .../jdk/vm/ci/hotspot/HotSpotNmethod.java | 38 ++++++- .../jdk/vm/ci/hotspot/CompilerToVMHelper.java | 4 +- .../code/test/CodeInvalidationReasonTest.java | 77 +++++++++++++ .../code/test/SimpleCodeInstallationTest.java | 6 +- .../vm/ci/code/test/TestHotSpotVMConfig.java | 4 +- 25 files changed, 271 insertions(+), 101 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index e2760689daa..57d22a38324 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -818,7 +818,7 @@ JRT_ENTRY(void, Runtime1::deoptimize(JavaThread* current, jint trap_request)) Deoptimization::DeoptReason reason = Deoptimization::trap_request_reason(trap_request); if (action == Deoptimization::Action_make_not_entrant) { - if (nm->make_not_entrant(nmethod::ChangeReason::C1_deoptimize)) { + if (nm->make_not_entrant(nmethod::InvalidationReason::C1_DEOPTIMIZE)) { if (reason == Deoptimization::Reason_tenured) { MethodData* trap_mdo = Deoptimization::get_method_data(current, method, true /*create_if_missing*/); if (trap_mdo != nullptr) { @@ -1110,7 +1110,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* current, C1StubId stub_id )) // safepoint, but if it's still alive then make it not_entrant. nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); if (nm != nullptr) { - nm->make_not_entrant(nmethod::ChangeReason::C1_codepatch); + nm->make_not_entrant(nmethod::InvalidationReason::C1_CODEPATCH); } Deoptimization::deoptimize_frame(current, caller_frame.id()); @@ -1358,7 +1358,7 @@ void Runtime1::patch_code(JavaThread* current, C1StubId stub_id) { // Make sure the nmethod is invalidated, i.e. made not entrant. nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); if (nm != nullptr) { - nm->make_not_entrant(nmethod::ChangeReason::C1_deoptimize_for_patching); + nm->make_not_entrant(nmethod::InvalidationReason::C1_DEOPTIMIZE_FOR_PATCHING); } } @@ -1486,7 +1486,7 @@ JRT_ENTRY(void, Runtime1::predicate_failed_trap(JavaThread* current)) nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); assert (nm != nullptr, "no more nmethod?"); - nm->make_not_entrant(nmethod::ChangeReason::C1_predicate_failed_trap); + nm->make_not_entrant(nmethod::InvalidationReason::C1_PREDICATE_FAILED_TRAP); methodHandle m(current, nm->method()); MethodData* mdo = m->method_data(); diff --git a/src/hotspot/share/ci/ciReplay.cpp b/src/hotspot/share/ci/ciReplay.cpp index f9829e88c4a..72ec2866c6e 100644 --- a/src/hotspot/share/ci/ciReplay.cpp +++ b/src/hotspot/share/ci/ciReplay.cpp @@ -802,7 +802,7 @@ class CompileReplay : public StackObj { // Make sure the existence of a prior compile doesn't stop this one nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, comp_level, true) : method->code(); if (nm != nullptr) { - nm->make_not_entrant(nmethod::ChangeReason::CI_replay); + nm->make_not_entrant(nmethod::InvalidationReason::CI_REPLAY); } replay_state = this; CompileBroker::compile_method(methodHandle(THREAD, method), entry_bci, comp_level, diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 9d505df8b72..6a5cc0f4a40 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1361,7 +1361,7 @@ void CodeCache::make_marked_nmethods_deoptimized() { while(iter.next()) { nmethod* nm = iter.method(); if (nm->is_marked_for_deoptimization() && !nm->has_been_deoptimized() && nm->can_be_deoptimized()) { - nm->make_not_entrant(nmethod::ChangeReason::marked_for_deoptimization); + nm->make_not_entrant(nmethod::InvalidationReason::MARKED_FOR_DEOPTIMIZATION); nm->make_deoptimized(); } } diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index acebaae6ba4..8e1f93e7288 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1975,12 +1975,12 @@ void nmethod::invalidate_osr_method() { } } -void nmethod::log_state_change(ChangeReason change_reason) const { +void nmethod::log_state_change(InvalidationReason invalidation_reason) const { if (LogCompilation) { if (xtty != nullptr) { ttyLocker ttyl; // keep the following output all in one block xtty->begin_elem("make_not_entrant thread='%zu' reason='%s'", - os::current_thread_id(), change_reason_to_string(change_reason)); + os::current_thread_id(), invalidation_reason_to_string(invalidation_reason)); log_identity(xtty); xtty->stamp(); xtty->end_elem(); @@ -1989,7 +1989,7 @@ void nmethod::log_state_change(ChangeReason change_reason) const { ResourceMark rm; stringStream ss(NEW_RESOURCE_ARRAY(char, 256), 256); - ss.print("made not entrant: %s", change_reason_to_string(change_reason)); + ss.print("made not entrant: %s", invalidation_reason_to_string(invalidation_reason)); CompileTask::print_ul(this, ss.freeze()); if (PrintCompilation) { @@ -2004,7 +2004,7 @@ void nmethod::unlink_from_method() { } // Invalidate code -bool nmethod::make_not_entrant(ChangeReason change_reason) { +bool nmethod::make_not_entrant(InvalidationReason invalidation_reason) { // This can be called while the system is already at a safepoint which is ok NoSafepointVerifier nsv; @@ -2073,7 +2073,7 @@ bool nmethod::make_not_entrant(ChangeReason change_reason) { assert(success, "Transition can't fail"); // Log the transition once - log_state_change(change_reason); + log_state_change(invalidation_reason); // Remove nmethod from method. unlink_from_method(); @@ -2084,7 +2084,7 @@ bool nmethod::make_not_entrant(ChangeReason change_reason) { // Invalidate can't occur while holding the NMethodState_lock JVMCINMethodData* nmethod_data = jvmci_nmethod_data(); if (nmethod_data != nullptr) { - nmethod_data->invalidate_nmethod_mirror(this); + nmethod_data->invalidate_nmethod_mirror(this, invalidation_reason); } #endif @@ -2122,7 +2122,9 @@ void nmethod::unlink() { // Clear the link between this nmethod and a HotSpotNmethod mirror JVMCINMethodData* nmethod_data = jvmci_nmethod_data(); if (nmethod_data != nullptr) { - nmethod_data->invalidate_nmethod_mirror(this); + nmethod_data->invalidate_nmethod_mirror(this, is_cold() ? + nmethod::InvalidationReason::UNLOADING_COLD : + nmethod::InvalidationReason::UNLOADING); } #endif diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 7453bdfa0ef..55e63c33e1a 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -471,77 +471,74 @@ class nmethod : public CodeBlob { void oops_do_set_strong_done(nmethod* old_head); public: - enum class ChangeReason : u1 { - C1_codepatch, - C1_deoptimize, - C1_deoptimize_for_patching, - C1_predicate_failed_trap, - CI_replay, - JVMCI_invalidate_nmethod, - JVMCI_invalidate_nmethod_mirror, - JVMCI_materialize_virtual_object, - JVMCI_new_installation, - JVMCI_register_method, - JVMCI_replacing_with_new_code, - JVMCI_reprofile, - marked_for_deoptimization, - missing_exception_handler, - not_used, - OSR_invalidation_back_branch, - OSR_invalidation_for_compiling_with_C1, - OSR_invalidation_of_lower_level, - set_native_function, - uncommon_trap, - whitebox_deoptimization, - zombie, + // If you change anything in this enum please patch + // vmStructs_jvmci.cpp accordingly. + enum class InvalidationReason : s1 { + NOT_INVALIDATED = -1, + C1_CODEPATCH, + C1_DEOPTIMIZE, + C1_DEOPTIMIZE_FOR_PATCHING, + C1_PREDICATE_FAILED_TRAP, + CI_REPLAY, + UNLOADING, + UNLOADING_COLD, + JVMCI_INVALIDATE, + JVMCI_MATERIALIZE_VIRTUAL_OBJECT, + JVMCI_REPLACED_WITH_NEW_CODE, + JVMCI_REPROFILE, + MARKED_FOR_DEOPTIMIZATION, + MISSING_EXCEPTION_HANDLER, + NOT_USED, + OSR_INVALIDATION_BACK_BRANCH, + OSR_INVALIDATION_FOR_COMPILING_WITH_C1, + OSR_INVALIDATION_OF_LOWER_LEVEL, + SET_NATIVE_FUNCTION, + UNCOMMON_TRAP, + WHITEBOX_DEOPTIMIZATION, + ZOMBIE, + INVALIDATION_REASONS_COUNT }; - static const char* change_reason_to_string(ChangeReason change_reason) { - switch (change_reason) { - case ChangeReason::C1_codepatch: + static const char* invalidation_reason_to_string(InvalidationReason invalidation_reason) { + switch (invalidation_reason) { + case InvalidationReason::C1_CODEPATCH: return "C1 code patch"; - case ChangeReason::C1_deoptimize: + case InvalidationReason::C1_DEOPTIMIZE: return "C1 deoptimized"; - case ChangeReason::C1_deoptimize_for_patching: + case InvalidationReason::C1_DEOPTIMIZE_FOR_PATCHING: return "C1 deoptimize for patching"; - case ChangeReason::C1_predicate_failed_trap: + case InvalidationReason::C1_PREDICATE_FAILED_TRAP: return "C1 predicate failed trap"; - case ChangeReason::CI_replay: + case InvalidationReason::CI_REPLAY: return "CI replay"; - case ChangeReason::JVMCI_invalidate_nmethod: - return "JVMCI invalidate nmethod"; - case ChangeReason::JVMCI_invalidate_nmethod_mirror: - return "JVMCI invalidate nmethod mirror"; - case ChangeReason::JVMCI_materialize_virtual_object: + case InvalidationReason::JVMCI_INVALIDATE: + return "JVMCI invalidate"; + case InvalidationReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT: return "JVMCI materialize virtual object"; - case ChangeReason::JVMCI_new_installation: - return "JVMCI new installation"; - case ChangeReason::JVMCI_register_method: - return "JVMCI register method"; - case ChangeReason::JVMCI_replacing_with_new_code: - return "JVMCI replacing with new code"; - case ChangeReason::JVMCI_reprofile: + case InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE: + return "JVMCI replaced with new code"; + case InvalidationReason::JVMCI_REPROFILE: return "JVMCI reprofile"; - case ChangeReason::marked_for_deoptimization: + case InvalidationReason::MARKED_FOR_DEOPTIMIZATION: return "marked for deoptimization"; - case ChangeReason::missing_exception_handler: + case InvalidationReason::MISSING_EXCEPTION_HANDLER: return "missing exception handler"; - case ChangeReason::not_used: + case InvalidationReason::NOT_USED: return "not used"; - case ChangeReason::OSR_invalidation_back_branch: + case InvalidationReason::OSR_INVALIDATION_BACK_BRANCH: return "OSR invalidation back branch"; - case ChangeReason::OSR_invalidation_for_compiling_with_C1: + case InvalidationReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1: return "OSR invalidation for compiling with C1"; - case ChangeReason::OSR_invalidation_of_lower_level: + case InvalidationReason::OSR_INVALIDATION_OF_LOWER_LEVEL: return "OSR invalidation of lower level"; - case ChangeReason::set_native_function: + case InvalidationReason::SET_NATIVE_FUNCTION: return "set native function"; - case ChangeReason::uncommon_trap: + case InvalidationReason::UNCOMMON_TRAP: return "uncommon trap"; - case ChangeReason::whitebox_deoptimization: + case InvalidationReason::WHITEBOX_DEOPTIMIZATION: return "whitebox deoptimization"; - case ChangeReason::zombie: + case InvalidationReason::ZOMBIE: return "zombie"; default: { assert(false, "Unhandled reason"); @@ -712,8 +709,8 @@ class nmethod : public CodeBlob { // alive. It is used when an uncommon trap happens. Returns true // if this thread changed the state of the nmethod or false if // another thread performed the transition. - bool make_not_entrant(ChangeReason change_reason); - bool make_not_used() { return make_not_entrant(ChangeReason::not_used); } + bool make_not_entrant(InvalidationReason invalidation_reason); + bool make_not_used() { return make_not_entrant(InvalidationReason::NOT_USED); } bool is_marked_for_deoptimization() const { return deoptimization_status() != not_marked; } bool has_been_deoptimized() const { return deoptimization_status() == deoptimize_done; } @@ -1026,7 +1023,7 @@ class nmethod : public CodeBlob { // Logging void log_identity(xmlStream* log) const; void log_new_nmethod() const; - void log_state_change(ChangeReason change_reason) const; + void log_state_change(InvalidationReason invalidation_reason) const; // Prints block-level comments, including nmethod specific block labels: void print_nmethod_labels(outputStream* stream, address block_begin, bool print_section_labels=true) const; diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index 5ca719d0309..1240fd21bbf 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -924,7 +924,7 @@ void CompilationPolicy::compile(const methodHandle& mh, int bci, CompLevel level nmethod* osr_nm = mh->lookup_osr_nmethod_for(bci, CompLevel_simple, false); if (osr_nm != nullptr && osr_nm->comp_level() > CompLevel_simple) { // Invalidate the existing OSR nmethod so that a compile at CompLevel_simple is permitted. - osr_nm->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_for_compiling_with_C1); + osr_nm->make_not_entrant(nmethod::InvalidationReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1); } compile(mh, bci, CompLevel_simple, THREAD); } @@ -1516,7 +1516,7 @@ void CompilationPolicy::method_back_branch_event(const methodHandle& mh, const m int osr_bci = nm->is_osr_method() ? nm->osr_entry_bci() : InvocationEntryBci; print_event(MAKE_NOT_ENTRANT, mh(), mh(), osr_bci, level); } - nm->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_back_branch); + nm->make_not_entrant(nmethod::InvalidationReason::OSR_INVALIDATION_BACK_BRANCH); } } // Fix up next_level if necessary to avoid deopts diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 001a40f74bc..22ced5a4411 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -1207,7 +1207,7 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject, assert(JVMCIENV->isa_HotSpotNmethod(installed_code_handle), "wrong type"); // Clear the link to an old nmethod first JVMCIObject nmethod_mirror = installed_code_handle; - JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, nmethod::ChangeReason::JVMCI_replacing_with_new_code, JVMCI_CHECK_0); + JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, true, nmethod::InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE, JVMCI_CHECK_0); } else { assert(JVMCIENV->isa_InstalledCode(installed_code_handle), "wrong type"); } @@ -1218,6 +1218,14 @@ C2V_VMENTRY_0(jint, installCode0, (JNIEnv *env, jobject, return result; C2V_END +C2V_VMENTRY_0(jobject, getInvalidationReasonDescription, (JNIEnv *env, jobject, jint invalidation_reason)) + HandleMark hm(THREAD); + JNIHandleMark jni_hm(thread); + nmethod::InvalidationReason reason = static_cast(invalidation_reason); + JVMCIObject desc = JVMCIENV->create_string(nmethod::invalidation_reason_to_string(reason), JVMCI_CHECK_NULL); + return JVMCIENV->get_jobject(desc); +C2V_END + C2V_VMENTRY(void, resetCompilationStatistics, (JNIEnv* env, jobject)) JVMCICompiler* compiler = JVMCICompiler::instance(true, CHECK); CompilerStatistics* stats = compiler->stats(); @@ -1383,7 +1391,7 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) nmethod* code = method->code(); if (code != nullptr) { - code->make_not_entrant(nmethod::ChangeReason::JVMCI_reprofile); + code->make_not_entrant(nmethod::InvalidationReason::JVMCI_REPROFILE); } MethodData* method_data = method->method_data(); @@ -1396,9 +1404,14 @@ C2V_VMENTRY(void, reprofile, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) C2V_END -C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize)) +C2V_VMENTRY(void, invalidateHotSpotNmethod, (JNIEnv* env, jobject, jobject hs_nmethod, jboolean deoptimize, jint invalidation_reason)) + int first = static_cast(nmethod::InvalidationReason::C1_CODEPATCH); + int last = static_cast(nmethod::InvalidationReason::INVALIDATION_REASONS_COUNT); + if (invalidation_reason < first || invalidation_reason >= last) { + JVMCI_THROW_MSG(IllegalArgumentException, err_msg("Invalid invalidation_reason: %d", invalidation_reason)); + } JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod); - JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, nmethod::ChangeReason::JVMCI_invalidate_nmethod, JVMCI_CHECK); + JVMCIENV->invalidate_nmethod_mirror(nmethod_mirror, deoptimize, static_cast(invalidation_reason), JVMCI_CHECK); C2V_END C2V_VMENTRY_NULL(jlongArray, collectCounters, (JNIEnv* env, jobject)) @@ -1823,7 +1836,7 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_ if (!fst.current()->is_compiled_frame()) { JVMCI_THROW_MSG(IllegalStateException, "compiled stack frame expected"); } - fst.current()->cb()->as_nmethod()->make_not_entrant(nmethod::ChangeReason::JVMCI_materialize_virtual_object); + fst.current()->cb()->as_nmethod()->make_not_entrant(nmethod::InvalidationReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT); } Deoptimization::deoptimize(thread, *fst.current(), Deoptimization::Reason_none); // look for the frame again as it has been updated by deopt (pc, deopt state...) @@ -3352,6 +3365,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getResolvedJavaType0", CC "(Ljava/lang/Object;JZ)" HS_KLASS, FN_PTR(getResolvedJavaType0)}, {CC "readConfiguration", CC "()[" OBJECT, FN_PTR(readConfiguration)}, {CC "installCode0", CC "(JJZ" HS_COMPILED_CODE "[" OBJECT INSTALLED_CODE "J[B)I", FN_PTR(installCode0)}, + {CC "getInvalidationReasonDescription", CC "(I)" STRING, FN_PTR(getInvalidationReasonDescription)}, {CC "getInstallCodeFlags", CC "()I", FN_PTR(getInstallCodeFlags)}, {CC "resetCompilationStatistics", CC "()V", FN_PTR(resetCompilationStatistics)}, {CC "disassembleCodeBlob", CC "(" INSTALLED_CODE ")" STRING, FN_PTR(disassembleCodeBlob)}, @@ -3360,7 +3374,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getLocalVariableTableStart", CC "(" HS_METHOD2 ")J", FN_PTR(getLocalVariableTableStart)}, {CC "getLocalVariableTableLength", CC "(" HS_METHOD2 ")I", FN_PTR(getLocalVariableTableLength)}, {CC "reprofile", CC "(" HS_METHOD2 ")V", FN_PTR(reprofile)}, - {CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD "Z)V", FN_PTR(invalidateHotSpotNmethod)}, + {CC "invalidateHotSpotNmethod", CC "(" HS_NMETHOD "ZI)V", FN_PTR(invalidateHotSpotNmethod)}, {CC "collectCounters", CC "()[J", FN_PTR(collectCounters)}, {CC "getCountersSize", CC "()I", FN_PTR(getCountersSize)}, {CC "setCountersSize", CC "(I)Z", FN_PTR(setCountersSize)}, diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 851ead247f1..ae64daf9f20 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1749,7 +1749,7 @@ void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* c } -void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nmethod::ChangeReason change_reason, JVMCI_TRAPS) { +void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nmethod::InvalidationReason invalidation_reason, JVMCI_TRAPS) { if (mirror.is_null()) { JVMCI_THROW(NullPointerException); } @@ -1772,7 +1772,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nm if (!deoptimize) { // Prevent future executions of the nmethod but let current executions complete. - nm->make_not_entrant(change_reason); + nm->make_not_entrant(invalidation_reason); // Do not clear the address field here as the Java code may still // want to later call this method with deoptimize == true. That requires @@ -1781,7 +1781,7 @@ void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, nm // Deoptimize the nmethod immediately. DeoptimizationScope deopt_scope; deopt_scope.mark(nm); - nm->make_not_entrant(change_reason); + nm->make_not_entrant(invalidation_reason); nm->make_deoptimized(); deopt_scope.deoptimize_marked(); diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index b7b7c8f6771..b49bba88b6b 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -462,7 +462,7 @@ class JVMCIEnv : public ResourceObj { // field of `mirror` to prevent it from being called. // If `deoptimize` is true, the nmethod is immediately deoptimized. // The HotSpotNmethod.address field is zero upon returning. - void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, nmethod::ChangeReason change_reason, JVMCI_TRAPS); + void invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimze, nmethod::InvalidationReason invalidation_reason, JVMCI_TRAPS); void initialize_installed_code(JVMCIObject installed_code, CodeBlob* cb, JVMCI_TRAPS); diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index d5fcd2aaaba..432fefe56d1 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp @@ -102,6 +102,7 @@ boolean_field(HotSpotNmethod, isDefault) \ long_field(HotSpotNmethod, compileIdSnapshot) \ object_field(HotSpotNmethod, method, "Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;") \ + int_field(HotSpotNmethod, invalidationReason) \ jvmci_constructor(HotSpotNmethod, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl;Ljava/lang/String;ZJ)V") \ end_class \ start_class(HotSpotCompiledCode, jdk_vm_ci_hotspot_HotSpotCompiledCode) \ diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 1f10e132eff..24ea4936822 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -797,7 +797,7 @@ void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) { Universe::heap()->register_nmethod(nm); } -void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) { +void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm, nmethod::InvalidationReason invalidation_reason) { oop nmethod_mirror = get_nmethod_mirror(nm); if (nmethod_mirror == nullptr) { return; @@ -816,12 +816,20 @@ void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) { HotSpotJVMCI::InstalledCode::set_address(jvmciEnv, nmethod_mirror, 0); HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0); HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0); + if (HotSpotJVMCI::HotSpotNmethod::invalidationReason(jvmciEnv, nmethod_mirror) == + static_cast(nmethod::InvalidationReason::NOT_INVALIDATED)) { + HotSpotJVMCI::HotSpotNmethod::set_invalidationReason(jvmciEnv, nmethod_mirror, static_cast(invalidation_reason)); + } } else if (nm->is_not_entrant()) { // Zero the entry point so any new invocation will fail but keep // the address link around that so that existing activations can // be deoptimized via the mirror (i.e. JVMCIEnv::invalidate_installed_code). HotSpotJVMCI::InstalledCode::set_entryPoint(jvmciEnv, nmethod_mirror, 0); HotSpotJVMCI::HotSpotInstalledCode::set_codeStart(jvmciEnv, nmethod_mirror, 0); + if (HotSpotJVMCI::HotSpotNmethod::invalidationReason(jvmciEnv, nmethod_mirror) == + static_cast(nmethod::InvalidationReason::NOT_INVALIDATED)) { + HotSpotJVMCI::HotSpotNmethod::set_invalidationReason(jvmciEnv, nmethod_mirror, static_cast(invalidation_reason)); + } } } @@ -2184,7 +2192,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV, tty->print_cr("Replacing method %s", method_name); } if (old != nullptr) { - old->make_not_entrant(nmethod::ChangeReason::JVMCI_register_method); + old->make_not_entrant(nmethod::InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE); } LogTarget(Info, nmethod, install) lt; diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index b49e09a1884..95c7d32f928 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -121,7 +121,7 @@ class JVMCINMethodData : public ResourceObj { // Clears the HotSpotNmethod.address field in the mirror. If nm // is dead, the HotSpotNmethod.entryPoint field is also cleared. - void invalidate_nmethod_mirror(nmethod* nm); + void invalidate_nmethod_mirror(nmethod* nm, nmethod::InvalidationReason invalidation_reason); // Gets the mirror from nm's oops table. oop get_nmethod_mirror(nmethod* nm); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index e26c815946d..bc930b1e1dc 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -564,7 +564,30 @@ declare_constant_with_value("LockStack::_end_offset", LockStack::end_offset()) \ declare_constant_with_value("OMCache::oop_to_oop_difference", OMCache::oop_to_oop_difference()) \ declare_constant_with_value("OMCache::oop_to_monitor_difference", OMCache::oop_to_monitor_difference()) \ - \ + \ + declare_constant(nmethod::InvalidationReason::NOT_INVALIDATED) \ + declare_constant(nmethod::InvalidationReason::C1_CODEPATCH) \ + declare_constant(nmethod::InvalidationReason::C1_DEOPTIMIZE) \ + declare_constant(nmethod::InvalidationReason::C1_DEOPTIMIZE_FOR_PATCHING) \ + declare_constant(nmethod::InvalidationReason::C1_PREDICATE_FAILED_TRAP) \ + declare_constant(nmethod::InvalidationReason::CI_REPLAY) \ + declare_constant(nmethod::InvalidationReason::UNLOADING) \ + declare_constant(nmethod::InvalidationReason::UNLOADING_COLD) \ + declare_constant(nmethod::InvalidationReason::JVMCI_INVALIDATE) \ + declare_constant(nmethod::InvalidationReason::JVMCI_MATERIALIZE_VIRTUAL_OBJECT) \ + declare_constant(nmethod::InvalidationReason::JVMCI_REPLACED_WITH_NEW_CODE) \ + declare_constant(nmethod::InvalidationReason::JVMCI_REPROFILE) \ + declare_constant(nmethod::InvalidationReason::MARKED_FOR_DEOPTIMIZATION) \ + declare_constant(nmethod::InvalidationReason::MISSING_EXCEPTION_HANDLER) \ + declare_constant(nmethod::InvalidationReason::NOT_USED) \ + declare_constant(nmethod::InvalidationReason::OSR_INVALIDATION_BACK_BRANCH) \ + declare_constant(nmethod::InvalidationReason::OSR_INVALIDATION_FOR_COMPILING_WITH_C1) \ + declare_constant(nmethod::InvalidationReason::OSR_INVALIDATION_OF_LOWER_LEVEL) \ + declare_constant(nmethod::InvalidationReason::SET_NATIVE_FUNCTION) \ + declare_constant(nmethod::InvalidationReason::UNCOMMON_TRAP) \ + declare_constant(nmethod::InvalidationReason::WHITEBOX_DEOPTIMIZATION) \ + declare_constant(nmethod::InvalidationReason::ZOMBIE) \ + \ declare_constant(CodeInstaller::VERIFIED_ENTRY) \ declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \ declare_constant(CodeInstaller::OSR_ENTRY) \ diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 1bb6b3bdf98..07b002f944e 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -3501,7 +3501,7 @@ void InstanceKlass::add_osr_nmethod(nmethod* n) { for (int l = CompLevel_limited_profile; l < n->comp_level(); l++) { nmethod *inv = lookup_osr_nmethod(n->method(), n->osr_entry_bci(), l, true); if (inv != nullptr && inv->is_in_use()) { - inv->make_not_entrant(nmethod::ChangeReason::OSR_invalidation_of_lower_level); + inv->make_not_entrant(nmethod::InvalidationReason::OSR_INVALIDATION_OF_LOWER_LEVEL); } } } diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 1a36fce23aa..bb7a0576eec 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -1028,7 +1028,7 @@ void Method::set_native_function(address function, bool post_event_flag) { // If so, we have to make it not_entrant. nmethod* nm = code(); // Put it into local variable to guard against concurrent updates if (nm != nullptr) { - nm->make_not_entrant(nmethod::ChangeReason::set_native_function); + nm->make_not_entrant(nmethod::InvalidationReason::SET_NATIVE_FUNCTION); } } diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 1507696c4d3..d025a8937c8 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -772,7 +772,7 @@ class VM_WhiteBoxDeoptimizeFrames : public VM_WhiteBoxOperation { if (_make_not_entrant) { nmethod* nm = CodeCache::find_nmethod(f->pc()); assert(nm != nullptr, "did not find nmethod"); - nm->make_not_entrant(nmethod::ChangeReason::whitebox_deoptimization); + nm->make_not_entrant(nmethod::InvalidationReason::WHITEBOX_DEOPTIMIZATION); } ++_result; } diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index ed84f2b294f..ceb09811f73 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1826,7 +1826,7 @@ void Deoptimization::deoptimize(JavaThread* thread, frame fr, DeoptReason reason #if INCLUDE_JVMCI address Deoptimization::deoptimize_for_missing_exception_handler(nmethod* nm) { // there is no exception handler for this pc => deoptimize - nm->make_not_entrant(nmethod::ChangeReason::missing_exception_handler); + nm->make_not_entrant(nmethod::InvalidationReason::MISSING_EXCEPTION_HANDLER); // Use Deoptimization::deoptimize for all of its side-effects: // gathering traps statistics, logging... @@ -2455,7 +2455,7 @@ JRT_ENTRY(void, Deoptimization::uncommon_trap_inner(JavaThread* current, jint tr // Recompile if (make_not_entrant) { - if (!nm->make_not_entrant(nmethod::ChangeReason::uncommon_trap)) { + if (!nm->make_not_entrant(nmethod::InvalidationReason::UNCOMMON_TRAP)) { return; // the call did not change nmethod's state } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 37ecb1c6f9a..abae0e10b37 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -1338,7 +1338,7 @@ void JavaThread::make_zombies() { // it is a Java nmethod nmethod* nm = CodeCache::find_nmethod(fst.current()->pc()); assert(nm != nullptr, "did not find nmethod"); - nm->make_not_entrant(nmethod::ChangeReason::zombie); + nm->make_not_entrant(nmethod::InvalidationReason::ZOMBIE); } } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 0cb56354498..b25f7a09256 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -654,6 +654,8 @@ native int installCode0(long compiledCodeBuffer, long failedSpeculationsAddress, byte[] speculations); + native String getInvalidationReasonDescription(int invalidationReason); + /** * Gets flags specifying optional parts of code info. Only if a flag is set, will the * corresponding code info being included in the {@linkplain HotSpotCompiledCodeStream @@ -842,7 +844,7 @@ void reprofile(HotSpotResolvedJavaMethodImpl method) { * {@code nmethod} associated with {@code nmethodMirror} is also made non-entrant and if * {@code deoptimize == true} any current activations of the {@code nmethod} are deoptimized. */ - native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize); + native void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize, int invalidationReason); /** * Collects the current values of all JVMCI benchmark counters, summed up over all threads. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java index a0130d1bda9..9545c9aa9ec 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCodeCacheProvider.java @@ -154,16 +154,20 @@ public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compile return logOrDump(resultInstalledCode, compiledCode); } - @Override - public void invalidateInstalledCode(InstalledCode installedCode) { + public void invalidateInstalledCode(InstalledCode installedCode, int invalidationReason) { if (installedCode instanceof HotSpotNmethod) { HotSpotNmethod nmethod = (HotSpotNmethod) installedCode; - nmethod.invalidate(true); + nmethod.invalidate(true, invalidationReason); } else { throw new IllegalArgumentException("Cannot invalidate a " + Objects.requireNonNull(installedCode).getClass().getName()); } } + @Override + public void invalidateInstalledCode(InstalledCode installedCode) { + invalidateInstalledCode(installedCode, jvmciInvalidationReason()); + } + @Override public TargetDescription getTarget() { return target; @@ -201,4 +205,8 @@ public int interpreterFrameSize(BytecodeFrame pos) { public void resetCompilationStatistics() { runtime.getCompilerToVM().resetCompilationStatistics(); } + + private static int jvmciInvalidationReason() { + return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::InvalidationReason::JVMCI_INVALIDATE", Integer.class); + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java index 9ed03f9749e..5c7089da6cb 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotNmethod.java @@ -27,6 +27,7 @@ import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InvalidInstalledCodeException; +import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -76,12 +77,19 @@ boolean inOopsTable() { */ private final long compileIdSnapshot; + /** + * Identify the reason that caused this nmethod to be invalidated. + * A value of -1 means that the nmethod was not invalidated. + */ + private int invalidationReason; + HotSpotNmethod(HotSpotResolvedJavaMethodImpl method, String name, boolean isDefault, long compileId) { super(name); this.method = method; this.isDefault = isDefault; boolean inOopsTable = !IS_IN_NATIVE_IMAGE && !isDefault; this.compileIdSnapshot = inOopsTable ? 0L : compileId; + this.invalidationReason = -1; assert inOopsTable || compileId != 0L : this; } @@ -122,9 +130,19 @@ public ResolvedJavaMethod getMethod() { return method; } + /** + * Invalidate this nmethod using the reason specified in {@code invalidationReason} and + * optionally deoptimize the method if {@code deoptimize} is set. + * @param deoptimize whether or not to deoptimize the method. + * @param invalidationReason invalidation reason code. + */ + public void invalidate(boolean deoptimize, int invalidationReason) { + compilerToVM().invalidateHotSpotNmethod(this, deoptimize, invalidationReason); + } + @Override public void invalidate(boolean deoptimize) { - compilerToVM().invalidateHotSpotNmethod(this, deoptimize); + invalidate(deoptimize, jvmciInvalidationReason()); } @Override @@ -188,4 +206,22 @@ public Object executeVarargs(Object... args) throws InvalidInstalledCodeExceptio public long getStart() { return isValid() ? super.getStart() : 0; } + + /** + * @return an integer representing the reason why this nmethod was invalidated. + */ + public int getInvalidationReason() { + return invalidationReason; + } + + /** + * @return a String describing the reason why this nmethod was invalidated. + */ + public String getInvalidationReasonDescription() { + return compilerToVM().getInvalidationReasonDescription(this.getInvalidationReason()); + } + + private static int jvmciInvalidationReason() { + return HotSpotJVMCIRuntime.runtime().config.getConstant("nmethod::InvalidationReason::JVMCI_INVALIDATE", Integer.class); + } } diff --git a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java index 4285000e27f..4c8e63d0a42 100644 --- a/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java +++ b/test/hotspot/jtreg/compiler/jvmci/common/patches/jdk.internal.vm.ci/jdk/vm/ci/hotspot/CompilerToVMHelper.java @@ -229,8 +229,8 @@ public static void reprofile(HotSpotResolvedJavaMethod method) { CTVM.reprofile((HotSpotResolvedJavaMethodImpl)method); } - public static void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize) { - CTVM.invalidateHotSpotNmethod(nmethodMirror, deoptimize); + public static void invalidateHotSpotNmethod(HotSpotNmethod nmethodMirror, boolean deoptimize, int invalidationReason) { + CTVM.invalidateHotSpotNmethod(nmethodMirror, deoptimize, invalidationReason); } public static long[] collectCounters() { diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java new file mode 100644 index 00000000000..624a2290509 --- /dev/null +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @requires vm.jvmci + * @requires vm.simpleArch == "x64" | vm.simpleArch == "aarch64" | vm.simpleArch == "riscv64" + * @library /test/lib / + * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot + * jdk.internal.vm.ci/jdk.vm.ci.meta + * jdk.internal.vm.ci/jdk.vm.ci.code + * jdk.internal.vm.ci/jdk.vm.ci.code.site + * jdk.internal.vm.ci/jdk.vm.ci.runtime + * jdk.internal.vm.ci/jdk.vm.ci.aarch64 + * jdk.internal.vm.ci/jdk.vm.ci.amd64 + * jdk.internal.vm.ci/jdk.vm.ci.riscv64 + * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java TestHotSpotVMConfig.java amd64/AMD64TestAssembler.java aarch64/AArch64TestAssembler.java riscv64/RISCV64TestAssembler.java + * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler jdk.vm.ci.code.test.CodeInvalidationReasonTest + */ + +package jdk.vm.ci.code.test; + +import jdk.test.lib.Asserts; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.hotspot.HotSpotNmethod; + +import org.junit.Test; + +import java.lang.reflect.Method; + +/** + * Test if setting HotSpotNmethod invalidation reason around works. + */ +public class CodeInvalidationReasonTest extends CodeInstallationTest { + + public static int add(int a, int b) { + return a + b; + } + + private static void compileAdd(TestAssembler asm) { + Register arg0 = asm.emitIntArg0(); + Register arg1 = asm.emitIntArg1(); + Register ret = asm.emitIntAdd(arg0, arg1); + asm.emitIntRet(ret); + } + + @Test + public void test() { + Method method = getMethod("add", int.class, int.class); + + HotSpotNmethod nmethod = test(CodeInvalidationReasonTest::compileAdd, method, 5, 7); + Asserts.assertEquals(-1 /* since it was not invalidated yet. */, nmethod.getInvalidationReason()); + + nmethod.invalidate(true, config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE); + Asserts.assertEquals(config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE, nmethod.getInvalidationReason()); + } +} diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java index c9c88024d99..4c76aea7a40 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,13 +71,13 @@ public void test() { Asserts.assertNotEquals(nmethod.getStart(), 0L); // Make nmethod non-entrant but still alive - nmethod.invalidate(false); + nmethod.invalidate(false, config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE); Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod); Asserts.assertTrue(nmethod.isAlive(), "code is not alive, i = " + nmethod); Asserts.assertEquals(nmethod.getStart(), 0L); // Deoptimize the nmethod and cut the link to it from the HotSpotNmethod - nmethod.invalidate(true); + nmethod.invalidate(true, config.NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE); Asserts.assertFalse(nmethod.isValid(), "code is valid, i = " + nmethod); Asserts.assertFalse(nmethod.isAlive(), "code is alive, i = " + nmethod); Asserts.assertEquals(nmethod.getStart(), 0L); diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java index db30229d34f..1e6c771b77b 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,6 +55,8 @@ public TestHotSpotVMConfig(HotSpotVMConfigStore config, Architecture arch) { public final int maxOopMapStackOffset = getFieldValue("CompilerToVM::Data::_max_oop_map_stack_offset", Integer.class, "int"); public final int heapWordSize = getConstant("HeapWordSize", Integer.class); + public final int NMETHOD_INVALIDATION_REASON_JVMCI_INVALIDATE = getConstant("nmethod::InvalidationReason::JVMCI_INVALIDATE", Integer.class); + public final boolean ropProtection; private Boolean initNmethodEntryBarrierConcurrentPatch(Architecture arch) { From dec42bebb836b2ea244dc19a5964dac828791135 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Thu, 19 Jun 2025 18:40:32 +0000 Subject: [PATCH 116/213] 8359394: GC cause cleanup Reviewed-by: shade, ysr, stefank --- src/hotspot/share/gc/shared/gcCause.cpp | 7 +++++-- src/hotspot/share/gc/shared/gcCause.hpp | 9 +++------ src/hotspot/share/gc/shared/gcVMOperations.cpp | 3 +-- .../share/gc/shenandoah/shenandoahControlThread.cpp | 2 +- .../share/classes/sun/jvm/hotspot/gc/shared/GCCause.java | 4 ++-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/hotspot/share/gc/shared/gcCause.cpp b/src/hotspot/share/gc/shared/gcCause.cpp index 51ce73861e0..489a5d32a90 100644 --- a/src/hotspot/share/gc/shared/gcCause.cpp +++ b/src/hotspot/share/gc/shared/gcCause.cpp @@ -89,11 +89,14 @@ const char* GCCause::to_string(GCCause::Cause cause) { case _dcmd_gc_run: return "Diagnostic Command"; + case _shenandoah_stop_vm: + return "Stopping VM"; + case _shenandoah_allocation_failure_evac: return "Allocation Failure During Evacuation"; - case _shenandoah_stop_vm: - return "Stopping VM"; + case _shenandoah_humongous_allocation_failure: + return "Humongous Allocation Failure"; case _shenandoah_concurrent_gc: return "Concurrent GC"; diff --git a/src/hotspot/share/gc/shared/gcCause.hpp b/src/hotspot/share/gc/shared/gcCause.hpp index ef96bf21567..ec7c664bbc1 100644 --- a/src/hotspot/share/gc/shared/gcCause.hpp +++ b/src/hotspot/share/gc/shared/gcCause.hpp @@ -55,7 +55,6 @@ class GCCause : public AllStatic { /* implementation independent, but reserved for GC use */ _no_gc, - _no_cause_specified, _allocation_failure, /* implementation specific */ @@ -99,14 +98,13 @@ class GCCause : public AllStatic { cause == GCCause::_wb_full_gc); } - inline static bool is_serviceability_requested_gc(GCCause::Cause - cause) { + inline static bool is_serviceability_requested_gc(GCCause::Cause cause) { return (cause == GCCause::_jvmti_force_gc || cause == GCCause::_heap_inspection || cause == GCCause::_heap_dump); } - // Causes for collection of the tenured gernation + // Causes for collection of the tenured generation inline static bool is_tenured_allocation_failure_gc(GCCause::Cause cause) { // _allocation_failure is the generic cause a collection which could result // in the collection of the tenured generation if there is not enough space @@ -117,8 +115,7 @@ class GCCause : public AllStatic { // Causes for collection of the young generation inline static bool is_allocation_failure_gc(GCCause::Cause cause) { // _allocation_failure is the generic cause a collection for allocation failure - return (cause == GCCause::_allocation_failure || - cause == GCCause::_shenandoah_allocation_failure_evac); + return cause == GCCause::_allocation_failure; } // Return a string describing the GCCause. diff --git a/src/hotspot/share/gc/shared/gcVMOperations.cpp b/src/hotspot/share/gc/shared/gcVMOperations.cpp index 1632dca61d5..7e24e47d4ef 100644 --- a/src/hotspot/share/gc/shared/gcVMOperations.cpp +++ b/src/hotspot/share/gc/shared/gcVMOperations.cpp @@ -99,8 +99,7 @@ static bool should_use_gclocker() { } bool VM_GC_Operation::doit_prologue() { - assert(((_gc_cause != GCCause::_no_gc) && - (_gc_cause != GCCause::_no_cause_specified)), "Illegal GCCause"); + assert(_gc_cause != GCCause::_no_gc, "Illegal GCCause"); // To be able to handle a GC the VM initialization needs to be completed. if (!is_init_completed()) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp index d8eb8e0a4e1..c0f3cf1a6a1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.cpp @@ -42,7 +42,7 @@ ShenandoahControlThread::ShenandoahControlThread() : ShenandoahController(), - _requested_gc_cause(GCCause::_no_cause_specified), + _requested_gc_cause(GCCause::_no_gc), _degen_point(ShenandoahGC::_degenerated_outside_cycle) { set_name("Shenandoah Control Thread"); create_and_start(); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java index 20fbb2128f0..918d34940f4 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/GCCause.java @@ -39,7 +39,6 @@ public enum GCCause { _wb_breakpoint ("WhiteBox Initiated Run to Breakpoint"), _no_gc ("No GC"), - _no_cause_specified ("Unknown GCCause"), _allocation_failure ("Allocation Failure"), _codecache_GC_threshold ("CodeCache GC Threshold"), @@ -54,8 +53,9 @@ public enum GCCause { _dcmd_gc_run ("Diagnostic Command"), - _shenandoah_allocation_failure_evac ("Allocation Failure During Evacuation"), _shenandoah_stop_vm ("Stopping VM"), + _shenandoah_allocation_failure_evac ("Allocation Failure During Evacuation"), + _shenandoah_humongous_allocation_failure("Humongous Allocation Failure"), _shenandoah_concurrent_gc ("Concurrent GC"), _shenandoah_upgrade_to_full_gc ("Upgrade To Full GC"), From 0dd50dbb3e6381af0ecc591ff1e5871bbc465732 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 19 Jun 2025 19:43:24 +0000 Subject: [PATCH 117/213] 8359825: Parallel: Simplify MutableNUMASpace::ensure_parsability Reviewed-by: tschatzl, sangheki --- .../share/gc/parallel/mutableNUMASpace.cpp | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 0c7d8de9bb5..ede1c570ece 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -92,18 +92,9 @@ void MutableNUMASpace::ensure_parsability() { LGRPSpace *ls = lgrp_spaces()->at(i); MutableSpace *s = ls->space(); if (s->top() < top()) { // For all spaces preceding the one containing top() - if (s->free_in_words() > 0) { - HeapWord* cur_top = s->top(); - size_t words_left_to_fill = pointer_delta(s->end(), s->top());; - while (words_left_to_fill > 0) { - size_t words_to_fill = MIN2(words_left_to_fill, CollectedHeap::filler_array_max_size()); - assert(words_to_fill >= CollectedHeap::min_fill_size(), - "Remaining size (%zu) is too small to fill (based on %zu and %zu)", - words_to_fill, words_left_to_fill, CollectedHeap::filler_array_max_size()); - CollectedHeap::fill_with_object(cur_top, words_to_fill); - cur_top += words_to_fill; - words_left_to_fill -= words_to_fill; - } + size_t free_words = s->free_in_words(); + if (free_words > 0) { + CollectedHeap::fill_with_objects(s->top(), free_words); } } else { return; From a6464b74a8c9b97653b292c18f5604d4d030a9cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Fri, 20 Jun 2025 01:33:54 +0000 Subject: [PATCH 118/213] 8358578: Small -XX:NMethodSizeLimit triggers "not in CodeBuffer memory" assert in C1 Reviewed-by: kvn, syan, thartmann --- src/hotspot/share/c1/c1_Compilation.cpp | 2 +- src/hotspot/share/c1/c1_Compilation.hpp | 8 +--- src/hotspot/share/c1/c1_Compiler.cpp | 5 +-- src/hotspot/share/c1/c1_globals.hpp | 6 --- .../compiler/arguments/TestC1Globals.java | 38 +------------------ .../compiler/c1/TestLinearScanOrderMain.java | 3 +- 6 files changed, 7 insertions(+), 55 deletions(-) diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index cf1f7e50086..3e2171eee08 100644 --- a/src/hotspot/share/c1/c1_Compilation.cpp +++ b/src/hotspot/share/c1/c1_Compilation.cpp @@ -330,7 +330,7 @@ bool Compilation::setup_code_buffer(CodeBuffer* code, int call_stub_estimate) { char* locs_buffer = NEW_RESOURCE_ARRAY(char, locs_buffer_size); code->insts()->initialize_shared_locs((relocInfo*)locs_buffer, locs_buffer_size / sizeof(relocInfo)); - code->initialize_consts_size(Compilation::desired_max_constant_size()); + code->initialize_consts_size(Compilation::desired_max_constant_size); // Call stubs + two deopt handlers (regular and MH) + exception handler int stub_size = (call_stub_estimate * LIR_Assembler::call_stub_size()) + LIR_Assembler::exception_handler_size() + diff --git a/src/hotspot/share/c1/c1_Compilation.hpp b/src/hotspot/share/c1/c1_Compilation.hpp index dab584ac3b0..a4bbe3442dd 100644 --- a/src/hotspot/share/c1/c1_Compilation.hpp +++ b/src/hotspot/share/c1/c1_Compilation.hpp @@ -216,12 +216,8 @@ class Compilation: public StackObj { const char* bailout_msg() const { return _bailout_msg; } const CompilationFailureInfo* first_failure_details() const { return _first_failure_details; } - static uint desired_max_code_buffer_size() { - return (uint)NMethodSizeLimit; // default 64K - } - static uint desired_max_constant_size() { - return desired_max_code_buffer_size() / 10; - } + const static uint desired_max_code_buffer_size = 64*K * wordSize; + const static uint desired_max_constant_size = desired_max_code_buffer_size / 10; static bool setup_code_buffer(CodeBuffer* cb, int call_stub_estimate); diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index b5fa7dcf247..8151acd99e0 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -79,7 +79,7 @@ void Compiler::initialize() { } uint Compiler::code_buffer_size() { - return Compilation::desired_max_code_buffer_size() + Compilation::desired_max_constant_size(); + return Compilation::desired_max_code_buffer_size + Compilation::desired_max_constant_size; } BufferBlob* Compiler::init_buffer_blob() { @@ -87,8 +87,7 @@ BufferBlob* Compiler::init_buffer_blob() { // compilation seems to be too expensive (at least on Intel win32). assert (CompilerThread::current()->get_buffer_blob() == nullptr, "Should initialize only once"); - // setup CodeBuffer. Preallocate a BufferBlob of size - // NMethodSizeLimit plus some extra space for constants. + // Setup CodeBuffer. BufferBlob* buffer_blob = BufferBlob::create("C1 temporary CodeBuffer", code_buffer_size()); if (buffer_blob != nullptr) { CompilerThread::current()->set_buffer_blob(buffer_blob); diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index ad259c8cc4e..e3615ae88ad 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -274,12 +274,6 @@ develop(bool, InstallMethods, true, \ "Install methods at the end of successful compilations") \ \ - /* The compiler assumes, in many places, that methods are at most 1MB. */ \ - /* Therefore, we restrict this flag to at most 1MB. */ \ - develop(intx, NMethodSizeLimit, (64*K)*wordSize, \ - "Maximum size of a compiled method.") \ - range(0, 1*M) \ - \ develop(intx, InstructionCountCutoff, 37000, \ "If GraphBuilder adds this many instructions, bails out") \ range(0, max_jint) \ diff --git a/test/hotspot/jtreg/compiler/arguments/TestC1Globals.java b/test/hotspot/jtreg/compiler/arguments/TestC1Globals.java index 2781f4e6b67..ba3d8aef191 100644 --- a/test/hotspot/jtreg/compiler/arguments/TestC1Globals.java +++ b/test/hotspot/jtreg/compiler/arguments/TestC1Globals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,42 +21,6 @@ * questions. */ -/** - * @test - * @bug 8316653 - * @requires vm.debug - * @summary Test flag with max value. - * - * @run main/othervm -XX:NMethodSizeLimit=1M - * compiler.arguments.TestC1Globals - */ - -/** - * @test - * @bug 8318817 - * @requires vm.debug - * @requires os.family == "linux" - * @summary Test flag with max value combined with transparent huge pages on - * Linux. - * - * @run main/othervm -XX:NMethodSizeLimit=1M - * -XX:+UseTransparentHugePages - * compiler.arguments.TestC1Globals - */ - -/** - * @test - * @bug 8320682 - * @requires vm.debug - * @summary Test flag with max value and specific compilation. - * - * @run main/othervm -XX:NMethodSizeLimit=1M - * -XX:CompileOnly=java.util.HashMap::putMapEntries - * -Xcomp - * compiler.arguments.TestC1Globals - * - */ - /** * @test * @bug 8322781 diff --git a/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java b/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java index a154427530a..8a8f4ca8853 100644 --- a/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java +++ b/test/hotspot/jtreg/compiler/c1/TestLinearScanOrderMain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * @bug 8207355 * @compile TestLinearScanOrder.jasm * @run main/othervm -Xcomp -XX:+TieredCompilation -XX:TieredStopAtLevel=1 - * -XX:+IgnoreUnrecognizedVMOptions -XX:NMethodSizeLimit=655360 * -XX:CompileCommand=compileonly,compiler.c1.TestLinearScanOrder::test * compiler.c1.TestLinearScanOrderMain */ From c51bed739d97167ae768e204dd8666d078d2e607 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 20 Jun 2025 03:09:57 +0000 Subject: [PATCH 119/213] 8335986: Test javax/swing/JCheckBox/4449413/bug4449413.java fails on Windows 11 x64 because RBMenuItem's and CBMenuItem's checkmark on the left side are not visible Reviewed-by: tr --- .../swing/JCheckBox/4449413/bug4449413.java | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java b/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java index 1efcfe58a31..d854961ea06 100644 --- a/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java +++ b/test/jdk/javax/swing/JCheckBox/4449413/bug4449413.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ /* @test * @bug 4449413 * @summary Tests that checkbox and radiobuttons' check marks are visible when background is black - * @author Ilya Boyandin * @run main/manual bug4449413 */ @@ -56,8 +55,16 @@ public class bug4449413 extends JFrame { + private static boolean isWindowsLF; + + private static String INSTRUCTIONS_WINDOWSLF = + "There are eight controls, JCheckBox/JRadioButton with black background\n" + + "and JRadioButtonMenuItem/JCheckboxMenuItem with gray background\n"; + private static final String INSTRUCTIONS = - "There are eight controls with black backgrounds.\n" + + "There are eight controls with black backgrounds.\n"; + + private static final String INSTRUCTIONS_COMMON = "Four enabled (on the left side) and four disabled (on the right side)\n" + "checkboxes and radiobuttons.\n\n" + "1. If at least one of the controls' check marks is not visible:\n" + @@ -82,6 +89,8 @@ boolean isMetalLookAndFeel() { } public static void main(String[] args) throws Exception { + isWindowsLF = "Windows".equals(UIManager.getLookAndFeel().getID()); + SwingUtilities.invokeLater(() -> { instance = new bug4449413(); instance.createAndShowGUI(); @@ -150,8 +159,10 @@ public void addComponentsToPane() { JTextArea instructionArea = new JTextArea( isMetalLookAndFeel() - ? INSTRUCTIONS + INSTRUCTIONS_ADDITIONS_METAL - : INSTRUCTIONS + ? INSTRUCTIONS + INSTRUCTIONS_COMMON + INSTRUCTIONS_ADDITIONS_METAL + : isWindowsLF + ? (INSTRUCTIONS_WINDOWSLF + INSTRUCTIONS_COMMON) + : (INSTRUCTIONS + INSTRUCTIONS_COMMON) ); instructionArea.setEditable(false); @@ -189,7 +200,13 @@ static AbstractButton createButton(int enabled, int type) { }; b.setOpaque(true); - b.setBackground(Color.black); + if (isWindowsLF + && ((b instanceof JRadioButtonMenuItem) + || (b instanceof JCheckBoxMenuItem))) { + b.setBackground(Color.lightGray); + } else { + b.setBackground(Color.black); + } b.setForeground(Color.white); b.setEnabled(enabled == 1); b.setSelected(true); From 33970629ac63eea6009fca7a34c8f333f1a60a37 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 20 Jun 2025 05:35:10 +0000 Subject: [PATCH 120/213] 8360069: Problem list CodeInvalidationReasonTest.java until JDK-8360049 is fixed Reviewed-by: dholmes --- test/hotspot/jtreg/ProblemList-zgc.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index 9571c717641..f071f8420eb 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -125,3 +125,5 @@ compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java 8343233 generic-aarch64 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java 8343233 generic-aarch64 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java 8343233 generic-aarch64 + +compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java 8360049 generic-aarch64 From 8f121a173ca2534c706682f6c68fbbb0b94ec057 Mon Sep 17 00:00:00 2001 From: Shruthi Date: Fri, 20 Jun 2025 10:13:01 +0000 Subject: [PATCH 121/213] 8317801: java/net/Socket/asyncClose/Race.java fails intermittently (aix) Reviewed-by: alanb, jkern --- .../unix/classes/sun/nio/ch/NativeThread.java | 13 ++++++++++++- .../unix/classes/sun/nio/ch/UnixDispatcher.java | 16 +++++++++++++--- .../unix/native/libnio/ch/NativeThread.c | 11 ++++++++++- test/jdk/ProblemList.txt | 2 -- 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/java.base/unix/classes/sun/nio/ch/NativeThread.java b/src/java.base/unix/classes/sun/nio/ch/NativeThread.java index 2ec67cc7d5c..8d0bcea48d9 100644 --- a/src/java.base/unix/classes/sun/nio/ch/NativeThread.java +++ b/src/java.base/unix/classes/sun/nio/ch/NativeThread.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -78,6 +78,17 @@ static boolean isVirtualThread(long tid) { return (tid == VIRTUAL_THREAD_ID); } + /** + * Return true if the operating system supports pending signals. If a signal is sent + * to a thread but cannot be delivered immediately then it will be delivered when the + * thread is in the appropriate state. + */ + static boolean supportPendingSignals() { + return supportPendingSignals0(); + } + + private static native boolean supportPendingSignals0(); + // Returns an opaque token representing the native thread underlying the // invoking Java thread. On systems that do not require signalling, this // method always returns 0. diff --git a/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java b/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java index fcd2d88d7a6..4cdd0c400ec 100644 --- a/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java +++ b/src/java.base/unix/classes/sun/nio/ch/UnixDispatcher.java @@ -29,21 +29,31 @@ import java.io.IOException; abstract class UnixDispatcher extends NativeDispatcher { + private static final boolean SUPPORTS_PENDING_SIGNALS = NativeThread.supportPendingSignals(); @Override void close(FileDescriptor fd) throws IOException { close0(fd); } - @Override - void implPreClose(FileDescriptor fd, long reader, long writer) throws IOException { - preClose0(fd); + private void signalThreads(long reader, long writer) { if (NativeThread.isNativeThread(reader)) NativeThread.signal(reader); if (NativeThread.isNativeThread(writer)) NativeThread.signal(writer); } + @Override + void implPreClose(FileDescriptor fd, long reader, long writer) throws IOException { + if (SUPPORTS_PENDING_SIGNALS) { + signalThreads(reader, writer); + } + preClose0(fd); + if (!SUPPORTS_PENDING_SIGNALS) { + signalThreads(reader, writer); + } + } + private static native void close0(FileDescriptor fd) throws IOException; private static native void preClose0(FileDescriptor fd) throws IOException; diff --git a/src/java.base/unix/native/libnio/ch/NativeThread.c b/src/java.base/unix/native/libnio/ch/NativeThread.c index f273b951569..d6d31b2b12b 100644 --- a/src/java.base/unix/native/libnio/ch/NativeThread.c +++ b/src/java.base/unix/native/libnio/ch/NativeThread.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,3 +88,12 @@ Java_sun_nio_ch_NativeThread_signal0(JNIEnv *env, jclass cl, jlong thread) #endif JNU_ThrowIOExceptionWithLastError(env, "Thread signal failed"); } + +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_NativeThread_supportPendingSignals0(JNIEnv *env, jclass cl) { +#if defined(_AIX) + return JNI_TRUE; +#else + return JNI_FALSE; +#endif +} diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 8c0e0bccde0..bf8d285c355 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -592,8 +592,6 @@ java/net/MulticastSocket/SetLoopbackMode.java 7122846,8308807 java/net/MulticastSocket/SetOutgoingIf.java 8308807 aix-ppc64 java/net/MulticastSocket/Test.java 7145658,8308807 macosx-all,aix-ppc64 -java/net/Socket/asyncClose/Race.java 8317801 aix-ppc64 - ############################################################################ # jdk_nio From c11f36e6200b6c39fd59530f28e9318c4153db49 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 20 Jun 2025 11:24:17 +0000 Subject: [PATCH 122/213] 8356708: C2: loop strip mining expansion doesn't take sunk stores into account Reviewed-by: rcastanedalo, epeter --- src/hotspot/share/opto/loopnode.cpp | 165 +++++++++++++++--- src/hotspot/share/opto/loopnode.hpp | 9 +- .../TestStoresSunkInOuterStripMinedLoop.java | 134 ++++++++++++++ 3 files changed, 281 insertions(+), 27 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopstripmining/TestStoresSunkInOuterStripMinedLoop.java diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 3130df54681..82446ec3110 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -298,19 +298,52 @@ IdealLoopTree* PhaseIdealLoop::insert_outer_loop(IdealLoopTree* loop, LoopNode* return outer_ilt; } -// Create a skeleton strip mined outer loop: a Loop head before the -// inner strip mined loop, a safepoint and an exit condition guarded -// by an opaque node after the inner strip mined loop with a backedge -// to the loop head. The inner strip mined loop is left as it is. Only -// once loop optimizations are over, do we adjust the inner loop exit -// condition to limit its number of iterations, set the outer loop -// exit condition and add Phis to the outer loop head. Some loop -// optimizations that operate on the inner strip mined loop need to be -// aware of the outer strip mined loop: loop unswitching needs to -// clone the outer loop as well as the inner, unrolling needs to only -// clone the inner loop etc. No optimizations need to change the outer -// strip mined loop as it is only a skeleton. -IdealLoopTree* PhaseIdealLoop::create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control, +// Create a skeleton strip mined outer loop: an OuterStripMinedLoop head before the inner strip mined CountedLoop, a +// SafePoint on exit of the inner CountedLoopEnd and an OuterStripMinedLoopEnd test that can't constant fold until loop +// optimizations are over. The inner strip mined loop is left as it is. Only once loop optimizations are over, do we +// adjust the inner loop exit condition to limit its number of iterations, set the outer loop exit condition and add +// Phis to the outer loop head. Some loop optimizations that operate on the inner strip mined loop need to be aware of +// the outer strip mined loop: loop unswitching needs to clone the outer loop as well as the inner, unrolling needs to +// only clone the inner loop etc. No optimizations need to change the outer strip mined loop as it is only a skeleton. +// +// Schematically: +// +// OuterStripMinedLoop -------| +// | | +// CountedLoop ----------- | | +// \- Phi (iv) -| | | +// / \ | | | +// CmpI AddI --| | | +// \ | | +// Bool | | +// \ | | +// CountedLoopEnd | | +// / \ | | +// IfFalse IfTrue--------| | +// | | +// SafePoint | +// | | +// OuterStripMinedLoopEnd | +// / \ | +// IfFalse IfTrue-----------| +// | +// +// +// As loop optimizations transform the inner loop, the outer strip mined loop stays mostly unchanged. The only exception +// is nodes referenced from the SafePoint and sunk from the inner loop: they end up in the outer strip mined loop. +// +// Not adding Phis to the outer loop head from the beginning, and only adding them after loop optimizations does not +// conform to C2's IR rules: any variable or memory slice that is mutated in a loop should have a Phi. The main +// motivation for such a design that doesn't conform to C2's IR rules is to allow existing loop optimizations to be +// mostly unaffected by the outer strip mined loop: the only extra step needed in most cases is to step over the +// OuterStripMinedLoop. The main drawback is that once loop optimizations are over, an extra step is needed to finish +// constructing the outer loop. This is handled by OuterStripMinedLoopNode::adjust_strip_mined_loop(). +// +// Adding Phis to the outer loop is largely straightforward: there needs to be one Phi in the outer loop for every Phi +// in the inner loop. Things may be more complicated for sunk Store nodes: there may not be any inner loop Phi left +// after sinking for a particular memory slice but the outer loop needs a Phi. See +// OuterStripMinedLoopNode::handle_sunk_stores_when_finishing_construction() +IdealLoopTree* PhaseIdealLoop::create_outer_strip_mined_loop(Node* init_control, IdealLoopTree* loop, float cl_prob, float le_fcnt, Node*& entry_control, Node*& iffalse) { Node* outer_test = intcon(0); @@ -2255,9 +2288,8 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ is_deleteable_safept(sfpt); IdealLoopTree* outer_ilt = nullptr; if (strip_mine_loop) { - outer_ilt = create_outer_strip_mined_loop(test, cmp, init_control, loop, - cl_prob, le->_fcnt, entry_control, - iffalse); + outer_ilt = create_outer_strip_mined_loop(init_control, loop, cl_prob, le->_fcnt, + entry_control, iffalse); } // Now setup a new CountedLoopNode to replace the existing LoopNode @@ -2870,10 +2902,11 @@ BaseCountedLoopNode* BaseCountedLoopNode::make(Node* entry, Node* backedge, Basi return new LongCountedLoopNode(entry, backedge); } -void OuterStripMinedLoopNode::fix_sunk_stores(CountedLoopEndNode* inner_cle, LoopNode* inner_cl, PhaseIterGVN* igvn, - PhaseIdealLoop* iloop) { - Node* cle_out = inner_cle->proj_out(false); - Node* cle_tail = inner_cle->proj_out(true); +void OuterStripMinedLoopNode::fix_sunk_stores_when_back_to_counted_loop(PhaseIterGVN* igvn, + PhaseIdealLoop* iloop) const { + CountedLoopNode* inner_cl = inner_counted_loop(); + IfFalseNode* cle_out = inner_loop_exit(); + if (cle_out->outcnt() > 1) { // Look for chains of stores that were sunk // out of the inner loop and are in the outer loop @@ -2988,11 +3021,90 @@ void OuterStripMinedLoopNode::fix_sunk_stores(CountedLoopEndNode* inner_cle, Loo } } +// The outer strip mined loop is initially only partially constructed. In particular Phis are omitted. +// See comment above: PhaseIdealLoop::create_outer_strip_mined_loop() +// We're now in the process of finishing the construction of the outer loop. For each Phi in the inner loop, a Phi in +// the outer loop was just now created. However, Sunk Stores cause an extra challenge: +// 1) If all Stores in the inner loop were sunk for a particular memory slice, there's no Phi left for that memory slice +// in the inner loop anymore, and hence we did not yet add a Phi for the outer loop. So an extra Phi must now be +// added for each chain of sunk Stores for a particular memory slice. +// 2) If some Stores were sunk and some left in the inner loop, a Phi was already created in the outer loop but +// its backedge input wasn't wired correctly to the last Store of the chain: the backedge input was set to the +// backedge of the inner loop Phi instead, but it needs to be the last Store of the chain in the outer loop. We now +// have to fix that too. +void OuterStripMinedLoopNode::handle_sunk_stores_when_finishing_construction(PhaseIterGVN* igvn) { + IfFalseNode* cle_exit_proj = inner_loop_exit(); + + // Find Sunk stores: Sunk stores are pinned on the loop exit projection of the inner loop. Indeed, because Sunk Stores + // modify the memory state captured by the SafePoint in the outer strip mined loop, they must be above it. The + // SafePoint's control input is the loop exit projection. It's also the only control out of the inner loop above the + // SafePoint. +#ifdef ASSERT + int stores_in_outer_loop_cnt = 0; + for (DUIterator_Fast imax, i = cle_exit_proj->fast_outs(imax); i < imax; i++) { + Node* u = cle_exit_proj->fast_out(i); + if (u->is_Store()) { + stores_in_outer_loop_cnt++; + } + } +#endif + + // Sunk stores are reachable from the memory state of the outer loop safepoint + SafePointNode* safepoint = outer_safepoint(); + MergeMemNode* mm = safepoint->in(TypeFunc::Memory)->isa_MergeMem(); + if (mm == nullptr) { + // There is no MergeMem, which should only happen if there was no memory node + // sunk out of the loop. + assert(stores_in_outer_loop_cnt == 0, "inconsistent"); + return; + } + DEBUG_ONLY(int stores_in_outer_loop_cnt2 = 0); + for (MergeMemStream mms(mm); mms.next_non_empty();) { + Node* mem = mms.memory(); + // Traverse up the chain of stores to find the first store pinned + // at the loop exit projection. + Node* last = mem; + Node* first = nullptr; + while (mem->is_Store() && mem->in(0) == cle_exit_proj) { + DEBUG_ONLY(stores_in_outer_loop_cnt2++); + first = mem; + mem = mem->in(MemNode::Memory); + } + if (first != nullptr) { + // Found a chain of Stores that were sunk + // Do we already have a memory Phi for that slice on the outer loop? If that is the case, that Phi was created + // by cloning an inner loop Phi. The inner loop Phi should have mem, the memory state of the first Store out of + // the inner loop, as input on the backedge. So does the outer loop Phi given it's a clone. + Node* phi = nullptr; + for (DUIterator_Fast imax, i = mem->fast_outs(imax); i < imax; i++) { + Node* u = mem->fast_out(i); + if (u->is_Phi() && u->in(0) == this && u->in(LoopBackControl) == mem) { + assert(phi == nullptr, "there should be only one"); + phi = u; + PRODUCT_ONLY(break); + } + } + if (phi == nullptr) { + // No outer loop Phi? create one + phi = PhiNode::make(this, last); + phi->set_req(EntryControl, mem); + phi = igvn->transform(phi); + igvn->replace_input_of(first, MemNode::Memory, phi); + } else { + // Fix memory state along the backedge: it should be the last sunk Store of the chain + igvn->replace_input_of(phi, LoopBackControl, last); + } + } + } + assert(stores_in_outer_loop_cnt == stores_in_outer_loop_cnt2, "inconsistent"); +} + void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { + verify_strip_mined(1); // Look for the outer & inner strip mined loop, reduce number of // iterations of the inner loop, set exit condition of outer loop, // construct required phi nodes for outer loop. - CountedLoopNode* inner_cl = unique_ctrl_out()->as_CountedLoop(); + CountedLoopNode* inner_cl = inner_counted_loop(); assert(inner_cl->is_strip_mined(), "inner loop should be strip mined"); if (LoopStripMiningIter == 0) { remove_outer_loop_and_safepoint(igvn); @@ -3010,7 +3122,7 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { inner_cl->clear_strip_mined(); return; } - CountedLoopEndNode* inner_cle = inner_cl->loopexit(); + CountedLoopEndNode* inner_cle = inner_counted_loop_end(); int stride = inner_cl->stride_con(); // For a min int stride, LoopStripMiningIter * stride overflows the int range for all values of LoopStripMiningIter @@ -3091,8 +3203,9 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { } Node* iv_phi = nullptr; - // Make a clone of each phi in the inner loop - // for the outer loop + // Make a clone of each phi in the inner loop for the outer loop + // When Stores were Sunk, after this step, a Phi may still be missing or its backedge incorrectly wired. See + // handle_sunk_stores_when_finishing_construction() for (uint i = 0; i < inner_cl->outcnt(); i++) { Node* u = inner_cl->raw_out(i); if (u->is_Phi()) { @@ -3111,6 +3224,8 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { } } + handle_sunk_stores_when_finishing_construction(igvn); + if (iv_phi != nullptr) { // Now adjust the inner loop's exit condition Node* limit = inner_cl->limit(); @@ -3166,7 +3281,7 @@ void OuterStripMinedLoopNode::transform_to_counted_loop(PhaseIterGVN* igvn, Phas CountedLoopEndNode* inner_cle = inner_cl->loopexit(); Node* safepoint = outer_safepoint(); - fix_sunk_stores(inner_cle, inner_cl, igvn, iloop); + fix_sunk_stores_when_back_to_counted_loop(igvn, iloop); // make counted loop exit test always fail ConINode* zero = igvn->intcon(0); diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 7670f6c620e..e056bda28e2 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -573,7 +573,8 @@ class LoopLimitNode : public Node { // Support for strip mining class OuterStripMinedLoopNode : public LoopNode { private: - static void fix_sunk_stores(CountedLoopEndNode* inner_cle, LoopNode* inner_cl, PhaseIterGVN* igvn, PhaseIdealLoop* iloop); + void fix_sunk_stores_when_back_to_counted_loop(PhaseIterGVN* igvn, PhaseIdealLoop* iloop) const; + void handle_sunk_stores_when_finishing_construction(PhaseIterGVN* igvn); public: OuterStripMinedLoopNode(Compile* C, Node *entry, Node *backedge) @@ -589,6 +590,10 @@ class OuterStripMinedLoopNode : public LoopNode { virtual OuterStripMinedLoopEndNode* outer_loop_end() const; virtual IfFalseNode* outer_loop_exit() const; virtual SafePointNode* outer_safepoint() const; + CountedLoopNode* inner_counted_loop() const { return unique_ctrl_out()->as_CountedLoop(); } + CountedLoopEndNode* inner_counted_loop_end() const { return inner_counted_loop()->loopexit(); } + IfFalseNode* inner_loop_exit() const { return inner_counted_loop_end()->proj_out(false)->as_IfFalse(); } + void adjust_strip_mined_loop(PhaseIterGVN* igvn); void remove_outer_loop_and_safepoint(PhaseIterGVN* igvn) const; @@ -1293,7 +1298,7 @@ class PhaseIdealLoop : public PhaseTransform { void add_parse_predicate(Deoptimization::DeoptReason reason, Node* inner_head, IdealLoopTree* loop, SafePointNode* sfpt); SafePointNode* find_safepoint(Node* back_control, Node* x, IdealLoopTree* loop); IdealLoopTree* insert_outer_loop(IdealLoopTree* loop, LoopNode* outer_l, Node* outer_ift); - IdealLoopTree* create_outer_strip_mined_loop(BoolNode *test, Node *cmp, Node *init_control, + IdealLoopTree* create_outer_strip_mined_loop(Node* init_control, IdealLoopTree* loop, float cl_prob, float le_fcnt, Node*& entry_control, Node*& iffalse); diff --git a/test/hotspot/jtreg/compiler/loopstripmining/TestStoresSunkInOuterStripMinedLoop.java b/test/hotspot/jtreg/compiler/loopstripmining/TestStoresSunkInOuterStripMinedLoop.java new file mode 100644 index 00000000000..0868f35bea4 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopstripmining/TestStoresSunkInOuterStripMinedLoop.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2025, Red Hat, Inc. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8356708 + * @summary C2: loop strip mining expansion doesn't take sunk stores into account + * + * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:LoopMaxUnroll=0 + * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM -XX:StressSeed=26601954 TestStoresSunkInOuterStripMinedLoop + * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:LoopMaxUnroll=0 + * -XX:+UnlockDiagnosticVMOptions -XX:+StressGCM TestStoresSunkInOuterStripMinedLoop + * @run main TestStoresSunkInOuterStripMinedLoop + * + */ + +public class TestStoresSunkInOuterStripMinedLoop { + private static int field; + private static volatile int volatileField; + + public static void main(String[] args) { + A a1 = new A(); + A a2 = new A(); + A a3 = new A(); + for (int i = 0; i < 20_000; i++) { + field = 0; + test1(); + if (field != 1500) { + throw new RuntimeException(field + " != 1500"); + } + a1.field = 0; + test2(a1, a2); + if (a1.field != 1500) { + throw new RuntimeException(a1.field + " != 1500"); + } + a1.field = 0; + test3(a1, a2); + if (a1.field != 1500) { + throw new RuntimeException(a1.field + " != 1500"); + } + a1.field = 0; + test4(a1, a2, a3); + if (a1.field != 1500) { + throw new RuntimeException(a1.field + " != 1500"); + } + } + } + + // Single store sunk in outer loop, no store in inner loop + private static float test1() { + int v = field; + float f = 1; + for (int i = 0; i < 1500; i++) { + f *= 2; + v++; + field = v; + } + return f; + } + + // Multiple stores sunk in outer loop, no store in inner loop + private static float test2(A a1, A a2) { + field = a1.field + a2.field; + volatileField = 42; + int v = a1.field; + float f = 1; + for (int i = 0; i < 1500; i++) { + f *= 2; + v++; + a1.field = v; + a2.field = v; + } + return f; + } + + // Store sunk in outer loop, store in inner loop + private static float test3(A a1, A a2) { + field = a1.field + a2.field; + volatileField = 42; + int v = a1.field; + float f = 1; + A a = a2; + for (int i = 0; i < 1500; i++) { + f *= 2; + v++; + a.field = v; + a = a1; + a2.field = v; + } + return f; + } + + // Multiple stores sunk in outer loop, store in inner loop + private static float test4(A a1, A a2, A a3) { + field = a1.field + a2.field + a3.field; + volatileField = 42; + int v = a1.field; + float f = 1; + A a = a2; + for (int i = 0; i < 1500; i++) { + f *= 2; + v++; + a.field = v; + a = a1; + a2.field = v; + a3.field = v; + } + return f; + } + + static class A { + int field; + } +} From ff54a6493a63cfbcaab7ec90c7db0135e98a7f0c Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Fri, 20 Jun 2025 13:25:38 +0000 Subject: [PATCH 123/213] 8360049: CodeInvalidationReasonTest.java fails with ZGC on AArch64 Reviewed-by: aph, shade --- test/hotspot/jtreg/ProblemList-zgc.txt | 2 -- .../src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java | 5 +++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index f071f8420eb..9571c717641 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -125,5 +125,3 @@ compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java 8343233 generic-aarch64 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java 8343233 generic-aarch64 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java 8343233 generic-aarch64 - -compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java 8360049 generic-aarch64 diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java index 1e6c771b77b..79a0aa60892 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/TestHotSpotVMConfig.java @@ -67,10 +67,11 @@ private Boolean initNmethodEntryBarrierConcurrentPatch(Architecture arch) { // There currently only 2 variants in use that differ only by the presence of a // dmb instruction int stw = getConstant("NMethodPatchingType::stw_instruction_and_data_patch", Integer.class); - int conc = getConstant("NMethodPatchingType::conc_data_patch", Integer.class); + int conc1 = getConstant("NMethodPatchingType::conc_data_patch", Integer.class); + int conc2 = getConstant("NMethodPatchingType::conc_instruction_and_data_patch", Integer.class); if (patchingType == stw) { patchConcurrent = false; - } else if (patchingType == conc) { + } else if (patchingType == conc1 || patchingType == conc2) { patchConcurrent = true; } else { throw new IllegalArgumentException("unsupported barrier sequence " + patchingType); From c6ab63d306511c43622fc1f37e1aed6d8abaaa09 Mon Sep 17 00:00:00 2001 From: Vladimir Petko Date: Fri, 20 Jun 2025 13:51:55 +0000 Subject: [PATCH 124/213] 8359735: [Ubuntu 25.10] java/lang/ProcessBuilder/Basic.java, java/lang/ProcessHandle/InfoTest.java fail due to rust-coreutils Reviewed-by: rriggs --- test/jdk/java/lang/ProcessBuilder/Basic.java | 4 ++-- test/jdk/java/lang/ProcessHandle/InfoTest.java | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/test/jdk/java/lang/ProcessBuilder/Basic.java b/test/jdk/java/lang/ProcessBuilder/Basic.java index 1995e9cecd1..c06ecbdb871 100644 --- a/test/jdk/java/lang/ProcessBuilder/Basic.java +++ b/test/jdk/java/lang/ProcessBuilder/Basic.java @@ -696,7 +696,7 @@ private static class TrueExe { public static String path() { return path; } private static final String path = path0(); private static String path0(){ - if (!Platform.isBusybox("/bin/true")) { + if (!Files.isSymbolicLink(Paths.get("/bin/true"))) { return "/bin/true"; } else { File trueExe = new File("true"); @@ -711,7 +711,7 @@ private static class FalseExe { public static String path() { return path; } private static final String path = path0(); private static String path0(){ - if (!Platform.isBusybox("/bin/false")) { + if (!Files.isSymbolicLink(Paths.get("/bin/false"))) { return "/bin/false"; } else { File falseExe = new File("false"); diff --git a/test/jdk/java/lang/ProcessHandle/InfoTest.java b/test/jdk/java/lang/ProcessHandle/InfoTest.java index 66ac2df830b..38c86db3b91 100644 --- a/test/jdk/java/lang/ProcessHandle/InfoTest.java +++ b/test/jdk/java/lang/ProcessHandle/InfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -295,10 +295,12 @@ public static void test3() { String expected = "sleep"; if (Platform.isWindows()) { expected = "sleep.exe"; - } else if (Platform.isBusybox("/bin/sleep")) { - // With busybox sleep is just a sym link to busybox. - // The busbox executable is seen as ProcessHandle.Info command. - expected = "busybox"; + } else if (Files.isSymbolicLink(Paths.get("/bin/sleep"))) { + // Busybox sleep is a symbolic link to /bin/busybox. + // Rust coreutils sleep is a symbolic link to coreutils + // The busbox/coreutils executables are seen as ProcessHandle.Info command. + Path executable = Files.readSymbolicLink(Paths.get("/bin/sleep")); + expected = executable.getFileName().toString(); } Assert.assertTrue(command.endsWith(expected), "Command: expected: \'" + expected + "\', actual: " + command); From 17cf49746d0c289bdf779c974cdc84a3ab32ab4b Mon Sep 17 00:00:00 2001 From: William Kemper Date: Fri, 20 Jun 2025 17:08:08 +0000 Subject: [PATCH 125/213] 8357550: GenShen crashes during freeze: assert(!chunk->requires_barriers()) failed Reviewed-by: kdnilsen, shade --- .../shenandoah/shenandoahGenerationalHeap.cpp | 23 +++++++++++++++++++ .../shenandoah/shenandoahGenerationalHeap.hpp | 2 ++ 2 files changed, 25 insertions(+) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 1f84feb20e8..731868310f4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -183,6 +183,29 @@ void ShenandoahGenerationalHeap::stop() { regulator_thread()->stop(); } +bool ShenandoahGenerationalHeap::requires_barriers(stackChunkOop obj) const { + if (is_idle()) { + return false; + } + + if (is_concurrent_young_mark_in_progress() && is_in_young(obj) && !marking_context()->allocated_after_mark_start(obj)) { + // We are marking young, this object is in young, and it is below the TAMS + return true; + } + + if (is_in_old(obj)) { + // Card marking barriers are required for objects in the old generation + return true; + } + + if (has_forwarded_objects()) { + // Object may have pointers that need to be updated + return true; + } + + return false; +} + void ShenandoahGenerationalHeap::evacuate_collection_set(bool concurrent) { ShenandoahRegionIterator regions; ShenandoahGenerationalEvacuationTask task(this, ®ions, concurrent, false /* only promote regions */); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp index cef5dfd7070..ed5a6f3d9a5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp @@ -128,6 +128,8 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap { void stop() override; + bool requires_barriers(stackChunkOop obj) const override; + // Used for logging the result of a region transfer outside the heap lock struct TransferResult { bool success; From 96f71a9a6bf7b52c50a1f52d4d401a48dc40480f Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Fri, 20 Jun 2025 19:48:41 +0000 Subject: [PATCH 126/213] 8255082: HotSpot Style Guide should permit noexcept Reviewed-by: kvn, dholmes, dcubed --- doc/hotspot-style.html | 53 ++++++++++++++++++++++++++++++++++++++++++ doc/hotspot-style.md | 51 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+) diff --git a/doc/hotspot-style.html b/doc/hotspot-style.html index 22fd7b8167b..dafd29d6f54 100644 --- a/doc/hotspot-style.html +++ b/doc/hotspot-style.html @@ -87,6 +87,7 @@

    HotSpot Coding Style

  • Inheriting constructors
  • Attributes
  • +
  • noexcept
  • Additional Permitted Features
  • @@ -1140,6 +1141,58 @@

    Attributes

    memory_order_consume.
  • [[deprecated]] - Not relevant in HotSpot code.
  • +

    noexcept

    +

    Use of noexcept exception specifications (n3050) are permitted with restrictions +described below.

    +
      +
    • Only the argument-less form of noexcept exception +specifications are permitted.
    • +
    • Allocation functions that may return nullptr to +indicate allocation failure must be declared noexcept.
    • +
    • All other uses of noexcept exception specifications are +forbidden.
    • +
    • noexcept expressions are forbidden.
    • +
    • Dynamic exception specifications are forbidden.
    • +
    +

    HotSpot is built with exceptions disabled, e.g. compile with +-fno-exceptions (gcc, clang) or no /EH option +(MSVC++). So why do we need to consider noexcept at all? +It's because noexcept exception specifications serve two +distinct purposes.

    +

    The first is to allow the compiler to avoid generating code or data +in support of exceptions being thrown by a function. But this is +unnecessary, because exceptions are disabled.

    +

    The second is to allow the compiler and library code to choose +different algorithms, depending on whether some function may throw +exceptions. This is only relevant to a certain set of functions.

    +
      +
    • Some allocation functions (operator new and +operator new[]) return nullptr to indicate +allocation failure. If a new expression calls such an +allocation function, it must check for and handle that possibility. +Declaring such a function noexcept informs the compiler +that nullptr is a possible result. If an allocation +function is not declared noexcept then the compiler may +elide that checking and handling for a new expression +calling that function.

    • +
    • Certain Standard Library facilities (notably containers) provide +different guarantees for some operations (and may choose different +algorithms to implement those operations), depending on whether certain +functions (constructors, copy/move operations, swap) are nothrow or not. +They detect this using type traits that test whether a function is +declared noexcept. This can have a significant performance +impact if, for example, copying is chosen over a potentially throwing +move. But this isn't relevant, since HotSpot forbids the use of most +Standard Library facilities.

    • +
    +

    HotSpot code can assume no exceptions will ever be thrown, even from +functions not declared noexcept. So HotSpot code doesn't +ever need to check, either with conditional exception specifications or +with noexcept expressions.

    +

    Dynamic exception specifications were deprecated in C++11. C++17 +removed all but throw(), with that remaining a deprecated +equivalent to noexcept.

    Additional Permitted Features

      diff --git a/doc/hotspot-style.md b/doc/hotspot-style.md index 92b756e10d3..0a0089ee454 100644 --- a/doc/hotspot-style.md +++ b/doc/hotspot-style.md @@ -1130,6 +1130,57 @@ The following attributes are expressly forbidden: * `[[carries_dependency]]` - Related to `memory_order_consume`. * `[[deprecated]]` - Not relevant in HotSpot code. +### noexcept + +Use of `noexcept` exception specifications +([n3050](http://wg21.link/n3050)) +are permitted with restrictions described below. + +* Only the argument-less form of `noexcept` exception specifications are +permitted. +* Allocation functions that may return `nullptr` to indicate allocation +failure must be declared `noexcept`. +* All other uses of `noexcept` exception specifications are forbidden. +* `noexcept` expressions are forbidden. +* Dynamic exception specifications are forbidden. + +HotSpot is built with exceptions disabled, e.g. compile with `-fno-exceptions` +(gcc, clang) or no `/EH` option (MSVC++). So why do we need to consider +`noexcept` at all? It's because `noexcept` exception specifications serve two +distinct purposes. + +The first is to allow the compiler to avoid generating code or data in support +of exceptions being thrown by a function. But this is unnecessary, because +exceptions are disabled. + +The second is to allow the compiler and library code to choose different +algorithms, depending on whether some function may throw exceptions. This is +only relevant to a certain set of functions. + +* Some allocation functions (`operator new` and `operator new[]`) return +`nullptr` to indicate allocation failure. If a `new` expression calls such an +allocation function, it must check for and handle that possibility. Declaring +such a function `noexcept` informs the compiler that `nullptr` is a possible +result. If an allocation function is not declared `noexcept` then the compiler +may elide that checking and handling for a `new` expression calling that +function. + +* Certain Standard Library facilities (notably containers) provide different +guarantees for some operations (and may choose different algorithms to +implement those operations), depending on whether certain functions +(constructors, copy/move operations, swap) are nothrow or not. They detect +this using type traits that test whether a function is declared `noexcept`. +This can have a significant performance impact if, for example, copying is +chosen over a potentially throwing move. But this isn't relevant, since +HotSpot forbids the use of most Standard Library facilities. + +HotSpot code can assume no exceptions will ever be thrown, even from functions +not declared `noexcept`. So HotSpot code doesn't ever need to check, either +with conditional exception specifications or with `noexcept` expressions. + +Dynamic exception specifications were deprecated in C++11. C++17 removed all +but `throw()`, with that remaining a deprecated equivalent to `noexcept`. + ### Additional Permitted Features * `alignof` From d627282f0c42c340db3b8b71121274b91638e09b Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 20 Jun 2025 19:53:17 +0000 Subject: [PATCH 127/213] 8360143: ProblemList runtime/NMT/VirtualAllocTestType.java Reviewed-by: rriggs --- test/hotspot/jtreg/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 1f62bfa8f29..78f37fd8c6d 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -111,6 +111,7 @@ runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/NMT/VirtualAllocCommitMerge.java 8309698 linux-s390x +runtime/NMT/VirtualAllocTestType.java 8359959 generic-all applications/jcstress/copy.java 8229852 linux-all From 81985d422d3a433c1248deec18e4fd9b9f780c2c Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 20 Jun 2025 22:22:41 +0000 Subject: [PATCH 128/213] 8358526: Clarify behavior of java.awt.HeadlessException constructed with no-args Reviewed-by: aivanov, honkar --- .../classes/java/awt/HeadlessException.java | 4 +- .../awt/Headless/HeadlessExceptionTest.java | 49 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 test/jdk/java/awt/Headless/HeadlessExceptionTest.java diff --git a/src/java.desktop/share/classes/java/awt/HeadlessException.java b/src/java.desktop/share/classes/java/awt/HeadlessException.java index 749f1d15d00..cff97ee8c3c 100644 --- a/src/java.desktop/share/classes/java/awt/HeadlessException.java +++ b/src/java.desktop/share/classes/java/awt/HeadlessException.java @@ -48,7 +48,9 @@ public class HeadlessException extends UnsupportedOperationException { private static final long serialVersionUID = 167183644944358563L; /** - * Constructs new {@code HeadlessException} with empty message. + * Constructs a new {@code HeadlessException} with {@code null} as its detail message. + * The default headless message may replace {@code null} in some cases, as outlined below. + *

      * For such {@code HeadlessException} the default headless error message * may be auto-generated for some platforms. * The text of the default headless message may depend on diff --git a/test/jdk/java/awt/Headless/HeadlessExceptionTest.java b/test/jdk/java/awt/Headless/HeadlessExceptionTest.java new file mode 100644 index 00000000000..c33f25ed934 --- /dev/null +++ b/test/jdk/java/awt/Headless/HeadlessExceptionTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.HeadlessException; + +/* + * @test 8358526 + * @summary Verify behaviour of no-args HeadlessException and getMessage + * @run main/othervm -Djava.awt.headless=true HeadlessExceptionTest + * @run main/othervm HeadlessExceptionTest + */ + +public class HeadlessExceptionTest { + + public static void main (String[] args) { + String nullmsg = new HeadlessException().getMessage(); + String emptymsg = new HeadlessException("").getMessage(); + System.out.println("nullmsg=" + nullmsg); + System.out.println("emptymsg=" + emptymsg); + if (nullmsg != null) { + if ("".equals(nullmsg)) { + throw new RuntimeException("empty message instead of null"); + } + if (!nullmsg.equals(emptymsg)) { + throw new RuntimeException("non-null messages differ"); + } + } + } +} From 6b4393917ae689818d67fcaf9cc61ca16ea6d426 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Mon, 23 Jun 2025 00:33:34 +0000 Subject: [PATCH 129/213] 8359270: C2: alignment check should consider base offset when emitting arraycopy runtime call Reviewed-by: thartmann, kvn --- src/hotspot/share/opto/library_call.cpp | 15 ++- src/hotspot/share/opto/stringopts.cpp | 11 +- .../stringopts/TestArrayCopySelect.java | 118 ++++++++++++++++++ 3 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/stringopts/TestArrayCopySelect.java diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index e9878cc0c77..6ddb63a9a2d 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -1575,9 +1575,14 @@ bool LibraryCallKit::inline_string_toBytesU() { Node* src_start = array_element_address(value, offset, T_CHAR); Node* dst_start = basic_plus_adr(newcopy, arrayOopDesc::base_offset_in_bytes(T_BYTE)); - // Check if src array address is aligned to HeapWordSize (dst is always aligned) - const TypeInt* toffset = gvn().type(offset)->is_int(); - bool aligned = toffset->is_con() && ((toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); + // Check if dst array address is aligned to HeapWordSize + bool aligned = (arrayOopDesc::base_offset_in_bytes(T_BYTE) % HeapWordSize == 0); + // If true, then check if src array address is aligned to HeapWordSize + if (aligned) { + const TypeInt* toffset = gvn().type(offset)->is_int(); + aligned = toffset->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) + + toffset->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); + } // Figure out which arraycopy runtime method to call (disjoint, uninitialized). const char* copyfunc_name = "arraycopy"; @@ -1658,8 +1663,8 @@ bool LibraryCallKit::inline_string_getCharsU() { // Check if array addresses are aligned to HeapWordSize const TypeInt* tsrc = gvn().type(src_begin)->is_int(); const TypeInt* tdst = gvn().type(dst_begin)->is_int(); - bool aligned = tsrc->is_con() && ((tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) && - tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); + bool aligned = tsrc->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_BYTE) + tsrc->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0) && + tdst->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_CHAR) + tdst->get_con() * type2aelembytes(T_CHAR)) % HeapWordSize == 0); // Figure out which arraycopy runtime method to call (disjoint, uninitialized). const char* copyfunc_name = "arraycopy"; diff --git a/src/hotspot/share/opto/stringopts.cpp b/src/hotspot/share/opto/stringopts.cpp index 641634b906e..28936a04219 100644 --- a/src/hotspot/share/opto/stringopts.cpp +++ b/src/hotspot/share/opto/stringopts.cpp @@ -1473,9 +1473,14 @@ void PhaseStringOpts::arraycopy(GraphKit& kit, IdealKit& ideal, Node* src_array, Node* src_ptr = __ array_element_address(src_array, __ intcon(0), T_BYTE); Node* dst_ptr = __ array_element_address(dst_array, start, T_BYTE); - // Check if destination address is aligned to HeapWordSize - const TypeInt* tdst = __ gvn().type(start)->is_int(); - bool aligned = tdst->is_con() && ((tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0); + // Check if src array address is aligned to HeapWordSize + bool aligned = (arrayOopDesc::base_offset_in_bytes(T_BYTE) % HeapWordSize == 0); + // If true, then check if dst array address is aligned to HeapWordSize + if (aligned) { + const TypeInt* tdst = __ gvn().type(start)->is_int(); + aligned = tdst->is_con() && ((arrayOopDesc::base_offset_in_bytes(T_BYTE) + + tdst->get_con() * type2aelembytes(T_BYTE)) % HeapWordSize == 0); + } // Figure out which arraycopy runtime method to call (disjoint, uninitialized). const char* copyfunc_name = "arraycopy"; address copyfunc_addr = StubRoutines::select_arraycopy_function(elembt, aligned, true, copyfunc_name, true); diff --git a/test/hotspot/jtreg/compiler/c2/irTests/stringopts/TestArrayCopySelect.java b/test/hotspot/jtreg/compiler/c2/irTests/stringopts/TestArrayCopySelect.java new file mode 100644 index 00000000000..4743f61ac39 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/stringopts/TestArrayCopySelect.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2025, Institute of Software, Chinese Academy of Sciences. + * All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.c2.irTests.stringopts; + +import compiler.lib.ir_framework.*; + +/** + * @test + * @bug 8359270 + * @requires vm.debug == true & vm.compiler2.enabled + * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="riscv64" | os.arch=="aarch64" + * @summary C2: alignment check should consider base offset when emitting arraycopy runtime call. + * @library /test/lib / + * @run driver compiler.c2.irTests.stringopts.TestArrayCopySelect + */ + +public class TestArrayCopySelect { + + public static final String input_strU = "\u0f21\u0f22\u0f23\u0f24\u0f25\u0f26\u0f27\u0f28"; + public static final char[] input_arrU = new char[] {'\u0f21', '\u0f22', '\u0f23', '\u0f24', + '\u0f25', '\u0f26', '\u0f27', '\u0f28'}; + + public static String output_strU; + public static char[] output_arrU; + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:-UseCompactObjectHeaders", + "-XX:-CompactStrings", + "-XX:CompileCommand=inline,java.lang.StringBuilder::toString", + "-XX:CompileCommand=inline,java.lang.StringUTF16::getChars", + "-XX:CompileCommand=inline,java.lang.StringUTF16::toBytes"); + + TestFramework.runWithFlags("-XX:+UseCompactObjectHeaders", + "-XX:-CompactStrings", + "-XX:CompileCommand=inline,java.lang.StringBuilder::toString", + "-XX:CompileCommand=inline,java.lang.StringUTF16::getChars", + "-XX:CompileCommand=inline,java.lang.StringUTF16::toBytes"); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "false"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", ">0"}) + static void testSBToStringAligned() { + // Exercise the StringBuilder.toString API + StringBuilder sb = new StringBuilder(input_strU); + output_strU = sb.append(input_strU).toString(); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "true"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", "0"}) + static void testSBToStringUnAligned() { + // Exercise the StringBuilder.toString API + StringBuilder sb = new StringBuilder(input_strU); + output_strU = sb.append(input_strU).toString(); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "false"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", ">0"}) + static void testStrUGetCharsAligned() { + // Exercise the StringUTF16.getChars API + output_arrU = input_strU.toCharArray(); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "true"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", "0"}) + static void testStrUGetCharsUnAligned() { + // Exercise the StringUTF16.getChars API + output_arrU = input_strU.toCharArray(); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "false"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", ">0"}) + static void testStrUtoBytesAligned() { + // Exercise the StringUTF16.toBytes API + output_strU = String.valueOf(input_arrU); + } + + @Test + @Warmup(10000) + @IR(applyIf = {"UseCompactObjectHeaders", "true"}, + counts = {IRNode.CALL_OF, "arrayof_jshort_disjoint_arraycopy", "0"}) + static void testStrUtoBytesUnAligned() { + // Exercise the StringUTF16.toBytes API + output_strU = String.valueOf(input_arrU); + } + +} From 620df7ec348598580884e3b9d45066495f0c40e5 Mon Sep 17 00:00:00 2001 From: Anjian Wen Date: Mon, 23 Jun 2025 02:31:53 +0000 Subject: [PATCH 130/213] 8359801: RISC-V: Simplify Interpreter::profile_taken_branch Reviewed-by: fyang, fjiang --- src/hotspot/cpu/riscv/interp_masm_riscv.cpp | 18 ++++-------------- src/hotspot/cpu/riscv/interp_masm_riscv.hpp | 2 +- src/hotspot/cpu/riscv/templateTable_riscv.cpp | 5 +---- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp index b909a884dc9..92f7169f471 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -1050,26 +1050,16 @@ void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { addi(sp, sp, 2 * wordSize); } -void InterpreterMacroAssembler::profile_taken_branch(Register mdp, - Register bumped_count) { +void InterpreterMacroAssembler::profile_taken_branch(Register mdp) { if (ProfileInterpreter) { Label profile_continue; // If no method data exists, go to profile_continue. - // Otherwise, assign to mdp test_method_data_pointer(mdp, profile_continue); // We are taking a branch. Increment the taken count. - Address data(mdp, in_bytes(JumpData::taken_offset())); - ld(bumped_count, data); - assert(DataLayout::counter_increment == 1, - "flow-free idiom only works with 1"); - addi(bumped_count, bumped_count, DataLayout::counter_increment); - Label L; - // eg: bumped_count=0x7fff ffff ffff ffff + 1 < 0. so we use <= 0; - blez(bumped_count, L); // skip store if counter overflow, - sd(bumped_count, data); - bind(L); + increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); + // The method data pointer needs to be updated to reflect the new target. update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset())); bind(profile_continue); @@ -1083,7 +1073,7 @@ void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) { // If no method data exists, go to profile_continue. test_method_data_pointer(mdp, profile_continue); - // We are taking a branch. Increment the not taken count. + // We are not taking a branch. Increment the not taken count. increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset())); // The method data pointer needs to be updated to correspond to diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp index 891db16b243..0732191ea83 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp @@ -261,7 +261,7 @@ class InterpreterMacroAssembler: public MacroAssembler { // narrow int return value void narrow(Register result); - void profile_taken_branch(Register mdp, Register bumped_count); + void profile_taken_branch(Register mdp); void profile_not_taken_branch(Register mdp); void profile_call(Register mdp); void profile_final_call(Register mdp); diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp index f6bf1e79f92..1011b8f1e7b 100644 --- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp @@ -1608,7 +1608,7 @@ void TemplateTable::float_cmp(bool is_float, int unordered_result) { } void TemplateTable::branch(bool is_jsr, bool is_wide) { - __ profile_taken_branch(x10, x11); + __ profile_taken_branch(x10); const ByteSize be_offset = MethodCounters::backedge_counter_offset() + InvocationCounter::counter_offset(); const ByteSize inv_offset = MethodCounters::invocation_counter_offset() + @@ -1657,7 +1657,6 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { if (UseLoopCounter) { // increment backedge counter for backward branches // x10: MDO - // x11: MDO bumped taken-count // x12: target offset __ bgtz(x12, dispatch); // count only if backward branch @@ -1666,12 +1665,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) { __ ld(t0, Address(xmethod, Method::method_counters_offset())); __ bnez(t0, has_counters); __ push_reg(x10); - __ push_reg(x11); __ push_reg(x12); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), xmethod); __ pop_reg(x12); - __ pop_reg(x11); __ pop_reg(x10); __ ld(t0, Address(xmethod, Method::method_counters_offset())); __ beqz(t0, dispatch); // No MethodCounters allocated, OutOfMemory From de34bb8e66253cef90ba79831dadec0252595b35 Mon Sep 17 00:00:00 2001 From: Srinivas Mandalika Date: Mon, 23 Jun 2025 04:54:43 +0000 Subject: [PATCH 131/213] 8359687: Use PassFailJFrame for java/awt/print/Dialog/DialogType.java Reviewed-by: abhiscxk, aivanov --- .../jdk/java/awt/print/Dialog/DialogType.java | 88 +++++++++++-------- 1 file changed, 51 insertions(+), 37 deletions(-) diff --git a/test/jdk/java/awt/print/Dialog/DialogType.java b/test/jdk/java/awt/print/Dialog/DialogType.java index 472b89e44f2..b8801583dd0 100644 --- a/test/jdk/java/awt/print/Dialog/DialogType.java +++ b/test/jdk/java/awt/print/Dialog/DialogType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,49 +26,63 @@ * @bug 6568874 * @key printer * @summary Verify the native dialog works with attribute sets. - * @run main/manual=yesno DialogType + * @library /java/awt/regtesthelpers /test/lib + * @build PassFailJFrame + * @run main/manual DialogType */ -import java.awt.print.*; -import javax.print.attribute.*; -import javax.print.attribute.standard.*; +import java.awt.print.PrinterJob; + +import javax.print.attribute.Attribute; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.DialogTypeSelection; + +import jtreg.SkippedException; public class DialogType { + private static PrinterJob job; + + private static final String INSTRUCTIONS = """ + Two print dialogs are shown in succession. + Click Cancel in the dialogs to close them. + + On macOS & on Windows, the first dialog is a native + dialog provided by the OS, the second dialog is + implemented in Swing, the dialogs differ in appearance. - static String[] instructions = { - "This test assumes and requires that you have a printer installed", - "It verifies that the dialogs behave properly when using new API", - "to optionally select a native dialog where one is present.", - "Two dialogs are shown in succession.", - "The test passes as long as no exceptions are thrown, *AND*", - "if running on Windows only, the first dialog is a native windows", - "control which differs in appearance from the second dialog", - "" - }; + The test passes as long as no exceptions are thrown. + (If there's an exception, the test will fail automatically.) - public static void main(String[] args) { + The test verifies that the dialogs behave properly when using new API + to optionally select a native dialog where one is present. + """; - for (int i=0;i Date: Mon, 23 Jun 2025 07:05:33 +0000 Subject: [PATCH 132/213] 8357220: Introduce a BSMAttributeEntry struct Co-authored-by: John R Rose Reviewed-by: sspitsyn, coleenp, matsaave --- .../share/cds/aotConstantPoolResolver.cpp | 6 +- src/hotspot/share/oops/constantPool.cpp | 14 +-- src/hotspot/share/oops/constantPool.hpp | 98 ++++++++++--------- .../prims/jvmtiClassFileReconstituter.cpp | 10 +- .../share/prims/jvmtiRedefineClasses.cpp | 9 +- src/hotspot/share/runtime/vmStructs.cpp | 12 +-- .../sun/jvm/hotspot/oops/ConstantPool.java | 8 +- 7 files changed, 84 insertions(+), 73 deletions(-) diff --git a/src/hotspot/share/cds/aotConstantPoolResolver.cpp b/src/hotspot/share/cds/aotConstantPoolResolver.cpp index 6ab63418e09..0eb7ddfbbf6 100644 --- a/src/hotspot/share/cds/aotConstantPoolResolver.cpp +++ b/src/hotspot/share/cds/aotConstantPoolResolver.cpp @@ -392,7 +392,7 @@ bool AOTConstantPoolResolver::check_lambda_metafactory_signature(ConstantPool* c } bool AOTConstantPoolResolver::check_lambda_metafactory_methodtype_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i) { - int mt_index = cp->operand_argument_index_at(bsms_attribute_index, arg_i); + int mt_index = cp->bsm_attribute_entry(bsms_attribute_index)->argument_index(arg_i); if (!cp->tag_at(mt_index).is_method_type()) { // malformed class? return false; @@ -408,7 +408,7 @@ bool AOTConstantPoolResolver::check_lambda_metafactory_methodtype_arg(ConstantPo } bool AOTConstantPoolResolver::check_lambda_metafactory_methodhandle_arg(ConstantPool* cp, int bsms_attribute_index, int arg_i) { - int mh_index = cp->operand_argument_index_at(bsms_attribute_index, arg_i); + int mh_index = cp->bsm_attribute_entry(bsms_attribute_index)->argument_index(arg_i); if (!cp->tag_at(mh_index).is_method_handle()) { // malformed class? return false; @@ -514,7 +514,7 @@ bool AOTConstantPoolResolver::is_indy_resolution_deterministic(ConstantPool* cp, } int bsms_attribute_index = cp->bootstrap_methods_attribute_index(cp_index); - int arg_count = cp->operand_argument_count_at(bsms_attribute_index); + int arg_count = cp->bsm_attribute_entry(bsms_attribute_index)->argument_count(); if (arg_count != 3) { // Malformed class? return false; diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 5b0ee298ddc..3223c56628e 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -1937,18 +1937,20 @@ int ConstantPool::find_matching_entry(int pattern_i, // Compare this constant pool's bootstrap specifier at idx1 to the constant pool // cp2's bootstrap specifier at idx2. bool ConstantPool::compare_operand_to(int idx1, const constantPoolHandle& cp2, int idx2) { - int k1 = operand_bootstrap_method_ref_index_at(idx1); - int k2 = cp2->operand_bootstrap_method_ref_index_at(idx2); + BSMAttributeEntry* e1 = bsm_attribute_entry(idx1); + BSMAttributeEntry* e2 = cp2->bsm_attribute_entry(idx2); + int k1 = e1->bootstrap_method_index(); + int k2 = e2->bootstrap_method_index(); bool match = compare_entry_to(k1, cp2, k2); if (!match) { return false; } - int argc = operand_argument_count_at(idx1); - if (argc == cp2->operand_argument_count_at(idx2)) { + int argc = e1->argument_count(); + if (argc == e2->argument_count()) { for (int j = 0; j < argc; j++) { - k1 = operand_argument_index_at(idx1, j); - k2 = cp2->operand_argument_index_at(idx2, j); + k1 = e1->argument_index(j); + k2 = e2->argument_index(j); match = compare_entry_to(k1, cp2, k2); if (!match) { return false; diff --git a/src/hotspot/share/oops/constantPool.hpp b/src/hotspot/share/oops/constantPool.hpp index cc9491d7935..be4a7a474d4 100644 --- a/src/hotspot/share/oops/constantPool.hpp +++ b/src/hotspot/share/oops/constantPool.hpp @@ -77,6 +77,43 @@ class CPKlassSlot { } }; +class BSMAttributeEntry { + friend class ConstantPool; + u2 _bootstrap_method_index; + u2 _argument_count; + + // The argument indexes are stored right after the object, in a contiguous array. + // [ bsmi_0 argc_0 arg_00 arg_01 ... arg_0N bsmi_1 argc_1 arg_10 ... arg_1N ... ] + // So in order to find the argument array, jump over ourselves. + const u2* argument_indexes() const { + return reinterpret_cast(this + 1); + } + u2* argument_indexes() { + return reinterpret_cast(this + 1); + } + // These are overlays on top of the operands array. Do not construct. + BSMAttributeEntry() = delete; + +public: + // Offsets for SA + enum { + _bsmi_offset = 0, + _argc_offset = 1, + _argv_offset = 2 + }; + + int bootstrap_method_index() const { + return _bootstrap_method_index; + } + int argument_count() const { + return _argument_count; + } + int argument_index(int n) const { + assert(checked_cast(n) < _argument_count, "oob"); + return argument_indexes()[n]; + } +}; + class ConstantPool : public Metadata { friend class VMStructs; friend class JVMCIVMStructs; @@ -519,10 +556,6 @@ class ConstantPool : public Metadata { assert(tag_at(cp_index).has_bootstrap(), "Corrupted constant pool"); return extract_low_short_from_int(*int_at_addr(cp_index)); } - int bootstrap_operand_base(int cp_index) { - int bsms_attribute_index = bootstrap_methods_attribute_index(cp_index); - return operand_offset_at(operands(), bsms_attribute_index); - } // The first part of the operands array consists of an index into the second part. // Extract a 32-bit index value from the first part. static int operand_offset_at(Array* operands, int bsms_attribute_index) { @@ -560,47 +593,26 @@ class ConstantPool : public Metadata { else return operand_offset_at(operands, nextidx); } - int bootstrap_operand_limit(int cp_index) { - int bsms_attribute_index = bootstrap_methods_attribute_index(cp_index); - return operand_limit_at(operands(), bsms_attribute_index); - } #endif //ASSERT - // Layout of InvokeDynamic and Dynamic bootstrap method specifier - // data in second part of operands array. This encodes one record in - // the BootstrapMethods attribute. The whole specifier also includes - // the name and type information from the main constant pool entry. - enum { - _indy_bsm_offset = 0, // CONSTANT_MethodHandle bsm - _indy_argc_offset = 1, // u2 argc - _indy_argv_offset = 2 // u2 argv[argc] - }; - // These functions are used in RedefineClasses for CP merge - int operand_offset_at(int bsms_attribute_index) { assert(0 <= bsms_attribute_index && bsms_attribute_index < operand_array_length(operands()), "Corrupted CP operands"); return operand_offset_at(operands(), bsms_attribute_index); } - u2 operand_bootstrap_method_ref_index_at(int bsms_attribute_index) { - int offset = operand_offset_at(bsms_attribute_index); - return operands()->at(offset + _indy_bsm_offset); - } - u2 operand_argument_count_at(int bsms_attribute_index) { - int offset = operand_offset_at(bsms_attribute_index); - u2 argc = operands()->at(offset + _indy_argc_offset); - return argc; - } - u2 operand_argument_index_at(int bsms_attribute_index, int j) { + + BSMAttributeEntry* bsm_attribute_entry(int bsms_attribute_index) { int offset = operand_offset_at(bsms_attribute_index); - return operands()->at(offset + _indy_argv_offset + j); + return reinterpret_cast(operands()->adr_at(offset)); } + int operand_next_offset_at(int bsms_attribute_index) { - int offset = operand_offset_at(bsms_attribute_index) + _indy_argv_offset - + operand_argument_count_at(bsms_attribute_index); - return offset; + BSMAttributeEntry* bsme = bsm_attribute_entry(bsms_attribute_index); + u2* argv_start = bsme->argument_indexes(); + int offset = argv_start - operands()->data(); + return offset + bsme->argument_count(); } // Compare a bootstrap specifier data in the operands arrays bool compare_operand_to(int bsms_attribute_index1, const constantPoolHandle& cp2, @@ -617,23 +629,19 @@ class ConstantPool : public Metadata { u2 bootstrap_method_ref_index_at(int cp_index) { assert(tag_at(cp_index).has_bootstrap(), "Corrupted constant pool"); - int op_base = bootstrap_operand_base(cp_index); - return operands()->at(op_base + _indy_bsm_offset); + int bsmai = bootstrap_methods_attribute_index(cp_index); + return bsm_attribute_entry(bsmai)->bootstrap_method_index(); } u2 bootstrap_argument_count_at(int cp_index) { assert(tag_at(cp_index).has_bootstrap(), "Corrupted constant pool"); - int op_base = bootstrap_operand_base(cp_index); - u2 argc = operands()->at(op_base + _indy_argc_offset); - DEBUG_ONLY(int end_offset = op_base + _indy_argv_offset + argc; - int next_offset = bootstrap_operand_limit(cp_index)); - assert(end_offset == next_offset, "matched ending"); - return argc; + int bsmai = bootstrap_methods_attribute_index(cp_index); + return bsm_attribute_entry(bsmai)->argument_count(); } u2 bootstrap_argument_index_at(int cp_index, int j) { - int op_base = bootstrap_operand_base(cp_index); - DEBUG_ONLY(int argc = operands()->at(op_base + _indy_argc_offset)); - assert((uint)j < (uint)argc, "oob"); - return operands()->at(op_base + _indy_argv_offset + j); + int bsmai = bootstrap_methods_attribute_index(cp_index); + BSMAttributeEntry* bsme = bsm_attribute_entry(bsmai); + assert((uint)j < (uint)bsme->argument_count(), "oob"); + return bsm_attribute_entry(bsmai)->argument_index(j); } // The following methods (name/signature/klass_ref_at, klass_ref_at_noresolve, diff --git a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp index 731db2e82f1..831f407e7ec 100644 --- a/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp +++ b/src/hotspot/share/prims/jvmtiClassFileReconstituter.cpp @@ -396,7 +396,7 @@ void JvmtiClassFileReconstituter::write_bootstrapmethod_attribute() { // calculate length of attribute u4 length = sizeof(u2); // num_bootstrap_methods for (int n = 0; n < num_bootstrap_methods; n++) { - u2 num_bootstrap_arguments = cpool()->operand_argument_count_at(n); + u2 num_bootstrap_arguments = cpool()->bsm_attribute_entry(n)->argument_count(); length += sizeof(u2); // bootstrap_method_ref length += sizeof(u2); // num_bootstrap_arguments length += (u4)sizeof(u2) * num_bootstrap_arguments; // bootstrap_arguments[num_bootstrap_arguments] @@ -406,12 +406,12 @@ void JvmtiClassFileReconstituter::write_bootstrapmethod_attribute() { // write attribute write_u2(checked_cast(num_bootstrap_methods)); for (int n = 0; n < num_bootstrap_methods; n++) { - u2 bootstrap_method_ref = cpool()->operand_bootstrap_method_ref_index_at(n); - u2 num_bootstrap_arguments = cpool()->operand_argument_count_at(n); - write_u2(bootstrap_method_ref); + BSMAttributeEntry* bsme = cpool()->bsm_attribute_entry(n); + u2 num_bootstrap_arguments = bsme->argument_count(); + write_u2(bsme->bootstrap_method_index()); write_u2(num_bootstrap_arguments); for (int arg = 0; arg < num_bootstrap_arguments; arg++) { - u2 bootstrap_argument = cpool()->operand_argument_index_at(n, arg); + u2 bootstrap_argument = bsme->argument_index(arg); write_u2(bootstrap_argument); } } diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 305af6df9be..ec4a6cd8c7f 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -659,10 +659,11 @@ u2 VM_RedefineClasses::find_or_append_indirect_entry(const constantPoolHandle& s // Append a bootstrap specifier into the merge_cp operands that is semantically equal // to the scratch_cp operands bootstrap specifier passed by the old_bs_i index. // Recursively append new merge_cp entries referenced by the new bootstrap specifier. -void VM_RedefineClasses::append_operand(const constantPoolHandle& scratch_cp, int old_bs_i, +void VM_RedefineClasses::append_operand(const constantPoolHandle& scratch_cp, const int old_bs_i, constantPoolHandle *merge_cp_p, int *merge_cp_length_p) { - u2 old_ref_i = scratch_cp->operand_bootstrap_method_ref_index_at(old_bs_i); + BSMAttributeEntry* old_bsme = scratch_cp->bsm_attribute_entry(old_bs_i); + u2 old_ref_i = old_bsme->bootstrap_method_index(); u2 new_ref_i = find_or_append_indirect_entry(scratch_cp, old_ref_i, merge_cp_p, merge_cp_length_p); if (new_ref_i != old_ref_i) { @@ -676,14 +677,14 @@ void VM_RedefineClasses::append_operand(const constantPoolHandle& scratch_cp, in // However, the operand_offset_at(0) was set in the extend_operands() call. int new_base = (new_bs_i == 0) ? (*merge_cp_p)->operand_offset_at(0) : (*merge_cp_p)->operand_next_offset_at(new_bs_i - 1); - u2 argc = scratch_cp->operand_argument_count_at(old_bs_i); + u2 argc = old_bsme->argument_count(); ConstantPool::operand_offset_at_put(merge_ops, _operands_cur_length, new_base); merge_ops->at_put(new_base++, new_ref_i); merge_ops->at_put(new_base++, argc); for (int i = 0; i < argc; i++) { - u2 old_arg_ref_i = scratch_cp->operand_argument_index_at(old_bs_i, i); + u2 old_arg_ref_i = old_bsme->argument_index(i); u2 new_arg_ref_i = find_or_append_indirect_entry(scratch_cp, old_arg_ref_i, merge_cp_p, merge_cp_length_p); merge_ops->at_put(new_base++, new_arg_ref_i); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 4e322c333a9..e248e0f05be 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1483,13 +1483,13 @@ \ declare_constant(Symbol::max_symbol_length) \ \ - /***********************************************/ \ - /* ConstantPool* layout enum for InvokeDynamic */ \ - /***********************************************/ \ + /******************************************************/ \ + /* BSMAttributeEntry* - layout enum for InvokeDynamic */ \ + /******************************************************/ \ \ - declare_constant(ConstantPool::_indy_bsm_offset) \ - declare_constant(ConstantPool::_indy_argc_offset) \ - declare_constant(ConstantPool::_indy_argv_offset) \ + declare_constant(BSMAttributeEntry::_bsmi_offset) \ + declare_constant(BSMAttributeEntry::_argc_offset) \ + declare_constant(BSMAttributeEntry::_argv_offset) \ \ /***************************************/ \ /* JavaThreadStatus enum */ \ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java index c1df1df9429..563d9d3ac4a 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,9 +100,9 @@ private static synchronized void initialize(TypeDataBase db) throws WrongTypeExc headerSize = type.getSize(); elementSize = 0; // fetch constants: - INDY_BSM_OFFSET = db.lookupIntConstant("ConstantPool::_indy_bsm_offset").intValue(); - INDY_ARGC_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argc_offset").intValue(); - INDY_ARGV_OFFSET = db.lookupIntConstant("ConstantPool::_indy_argv_offset").intValue(); + INDY_BSM_OFFSET = db.lookupIntConstant("BSMAttributeEntry::_bsmi_offset").intValue(); + INDY_ARGC_OFFSET = db.lookupIntConstant("BSMAttributeEntry::_argc_offset").intValue(); + INDY_ARGV_OFFSET = db.lookupIntConstant("BSMAttributeEntry::_argv_offset").intValue(); } public ConstantPool(Address addr) { From 9ae39b62b91ffacc6473534d96679f3282c612cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Mon, 23 Jun 2025 07:47:17 +0000 Subject: [PATCH 133/213] 8355276: Sort C2 includes Reviewed-by: kvn, thartmann --- src/hotspot/share/opto/addnode.cpp | 2 +- src/hotspot/share/opto/block.cpp | 2 +- src/hotspot/share/opto/bytecodeInfo.cpp | 2 +- src/hotspot/share/opto/c2compiler.cpp | 4 ++-- src/hotspot/share/opto/callGenerator.cpp | 2 +- src/hotspot/share/opto/callnode.cpp | 4 ++-- src/hotspot/share/opto/castnode.cpp | 2 +- src/hotspot/share/opto/cfgnode.cpp | 2 +- src/hotspot/share/opto/classes.cpp | 2 +- src/hotspot/share/opto/compile.cpp | 2 +- src/hotspot/share/opto/compile.hpp | 8 ++++---- src/hotspot/share/opto/divnode.cpp | 4 ++-- src/hotspot/share/opto/escape.cpp | 8 ++++---- src/hotspot/share/opto/gcm.cpp | 2 +- src/hotspot/share/opto/graphKit.cpp | 6 +++--- src/hotspot/share/opto/idealKit.hpp | 2 +- src/hotspot/share/opto/ifnode.cpp | 2 +- src/hotspot/share/opto/intrinsicnode.cpp | 6 +++--- src/hotspot/share/opto/intrinsicnode.hpp | 2 +- src/hotspot/share/opto/lcm.cpp | 2 +- src/hotspot/share/opto/library_call.cpp | 4 ++-- src/hotspot/share/opto/library_call.hpp | 2 +- src/hotspot/share/opto/loopPredicate.cpp | 1 + src/hotspot/share/opto/loopTransform.cpp | 2 +- src/hotspot/share/opto/loopopts.cpp | 3 +-- src/hotspot/share/opto/macroArrayCopy.cpp | 6 +++--- src/hotspot/share/opto/memnode.cpp | 2 +- src/hotspot/share/opto/mempointer.cpp | 4 ++-- src/hotspot/share/opto/output.cpp | 2 +- src/hotspot/share/opto/printinlining.cpp | 4 ++-- src/hotspot/share/opto/printinlining.hpp | 4 ++-- src/hotspot/share/opto/rangeinference.hpp | 1 + src/hotspot/share/opto/runtime.cpp | 4 ++-- src/hotspot/share/opto/superword.cpp | 2 +- src/hotspot/share/opto/superwordVTransformBuilder.hpp | 2 +- src/hotspot/share/opto/type.cpp | 4 ++-- src/hotspot/share/opto/vectorization.hpp | 4 ++-- src/hotspot/share/opto/vectornode.cpp | 4 ++-- src/hotspot/share/opto/vtransform.cpp | 4 ++-- test/hotspot/jtreg/sources/TestIncludesAreSorted.java | 1 + 40 files changed, 64 insertions(+), 62 deletions(-) diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 143398c57d0..92fb54a3a13 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -32,8 +32,8 @@ #include "opto/mulnode.hpp" #include "opto/phaseX.hpp" #include "opto/subnode.hpp" -#include "runtime/stubRoutines.hpp" #include "opto/utilities/xor.hpp" +#include "runtime/stubRoutines.hpp" // Portions of code courtesy of Clifford Click diff --git a/src/hotspot/share/opto/block.cpp b/src/hotspot/share/opto/block.cpp index e920f6f1fa3..7d3d4ec16f4 100644 --- a/src/hotspot/share/opto/block.cpp +++ b/src/hotspot/share/opto/block.cpp @@ -22,10 +22,10 @@ * */ +#include "compiler/compilerDirectives.hpp" #include "libadt/vectset.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" -#include "compiler/compilerDirectives.hpp" #include "opto/block.hpp" #include "opto/cfgnode.hpp" #include "opto/chaitin.hpp" diff --git a/src/hotspot/share/opto/bytecodeInfo.cpp b/src/hotspot/share/opto/bytecodeInfo.cpp index e618a708f61..547cf2f6a38 100644 --- a/src/hotspot/share/opto/bytecodeInfo.cpp +++ b/src/hotspot/share/opto/bytecodeInfo.cpp @@ -26,8 +26,8 @@ #include "classfile/vmSymbols.hpp" #include "compiler/compilationPolicy.hpp" #include "compiler/compileBroker.hpp" -#include "compiler/compilerEvent.hpp" #include "compiler/compileLog.hpp" +#include "compiler/compilerEvent.hpp" #include "interpreter/linkResolver.hpp" #include "jfr/jfrEvents.hpp" #include "oops/objArrayKlass.hpp" diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index 0c642211e1f..ea8b6853298 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -25,15 +25,15 @@ #include "classfile/vmClasses.hpp" #include "compiler/compilationMemoryStatistic.hpp" #include "compiler/compilerDefinitions.inline.hpp" -#include "runtime/handles.inline.hpp" #include "jfr/support/jfrIntrinsics.hpp" #include "opto/c2compiler.hpp" #include "opto/compile.hpp" #include "opto/optoreg.hpp" #include "opto/output.hpp" #include "opto/runtime.hpp" -#include "runtime/stubRoutines.hpp" #include "runtime/globals_extension.hpp" +#include "runtime/handles.inline.hpp" +#include "runtime/stubRoutines.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index e0ad2f00ab5..e09d8cabe2c 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -24,9 +24,9 @@ #include "ci/bcEscapeAnalyzer.hpp" #include "ci/ciCallSite.hpp" -#include "ci/ciObjArray.hpp" #include "ci/ciMemberName.hpp" #include "ci/ciMethodHandle.hpp" +#include "ci/ciObjArray.hpp" #include "classfile/javaClasses.hpp" #include "compiler/compileLog.hpp" #include "opto/addnode.hpp" diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 3527e46c24b..a6203c94cff 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -22,8 +22,9 @@ * */ -#include "compiler/compileLog.hpp" #include "ci/bcEscapeAnalyzer.hpp" +#include "code/vmreg.hpp" +#include "compiler/compileLog.hpp" #include "compiler/oopMap.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/c2/barrierSetC2.hpp" @@ -43,7 +44,6 @@ #include "opto/runtime.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/powerOfTwo.hpp" -#include "code/vmreg.hpp" // Portions of code courtesy of Clifford Click diff --git a/src/hotspot/share/opto/castnode.cpp b/src/hotspot/share/opto/castnode.cpp index b835950dfdb..96f5ba7e693 100644 --- a/src/hotspot/share/opto/castnode.cpp +++ b/src/hotspot/share/opto/castnode.cpp @@ -22,6 +22,7 @@ * */ +#include "castnode.hpp" #include "opto/addnode.hpp" #include "opto/callnode.hpp" #include "opto/castnode.hpp" @@ -30,7 +31,6 @@ #include "opto/phaseX.hpp" #include "opto/subnode.hpp" #include "opto/type.hpp" -#include "castnode.hpp" #include "utilities/checkedCast.hpp" //============================================================================= diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 92f6c938dba..ef912ff471a 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -35,8 +35,8 @@ #include "opto/loopnode.hpp" #include "opto/machnode.hpp" #include "opto/movenode.hpp" -#include "opto/narrowptrnode.hpp" #include "opto/mulnode.hpp" +#include "opto/narrowptrnode.hpp" #include "opto/phaseX.hpp" #include "opto/regalloc.hpp" #include "opto/regmask.hpp" diff --git a/src/hotspot/share/opto/classes.cpp b/src/hotspot/share/opto/classes.cpp index 61d164773a2..b760a179b57 100644 --- a/src/hotspot/share/opto/classes.cpp +++ b/src/hotspot/share/opto/classes.cpp @@ -35,8 +35,8 @@ #include "opto/locknode.hpp" #include "opto/loopnode.hpp" #include "opto/machnode.hpp" -#include "opto/memnode.hpp" #include "opto/mathexactnode.hpp" +#include "opto/memnode.hpp" #include "opto/movenode.hpp" #include "opto/mulnode.hpp" #include "opto/multnode.hpp" diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index d256b7a7d5e..ebc2b28e4ad 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -33,9 +33,9 @@ #include "compiler/compilationMemoryStatistic.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compileLog.hpp" +#include "compiler/compiler_globals.hpp" #include "compiler/compilerDefinitions.hpp" #include "compiler/compilerOracle.hpp" -#include "compiler/compiler_globals.hpp" #include "compiler/disassembler.hpp" #include "compiler/oopMap.hpp" #include "gc/shared/barrierSet.hpp" diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 678b05a8517..69244a6d178 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -28,17 +28,18 @@ #include "asm/codeBuffer.hpp" #include "ci/compilerInterface.hpp" #include "code/debugInfoRec.hpp" -#include "compiler/compiler_globals.hpp" +#include "compiler/cHeapStringHolder.hpp" #include "compiler/compileBroker.hpp" +#include "compiler/compiler_globals.hpp" #include "compiler/compilerEvent.hpp" -#include "compiler/cHeapStringHolder.hpp" #include "libadt/dict.hpp" #include "libadt/vectset.hpp" #include "memory/resourceArea.hpp" #include "oops/methodData.hpp" #include "opto/idealGraphPrinter.hpp" -#include "opto/phasetype.hpp" #include "opto/phase.hpp" +#include "opto/phasetype.hpp" +#include "opto/printinlining.hpp" #include "opto/regmask.hpp" #include "runtime/deoptimization.hpp" #include "runtime/sharedRuntime.hpp" @@ -46,7 +47,6 @@ #include "runtime/vmThread.hpp" #include "utilities/ticks.hpp" #include "utilities/vmEnums.hpp" -#include "opto/printinlining.hpp" class AbstractLockNode; class AddPNode; diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp index a70194274a7..a77eed208c8 100644 --- a/src/hotspot/share/opto/divnode.cpp +++ b/src/hotspot/share/opto/divnode.cpp @@ -28,13 +28,13 @@ #include "opto/convertnode.hpp" #include "opto/divnode.hpp" #include "opto/machnode.hpp" -#include "opto/movenode.hpp" #include "opto/matcher.hpp" +#include "opto/movenode.hpp" #include "opto/mulnode.hpp" #include "opto/phaseX.hpp" +#include "opto/runtime.hpp" #include "opto/subnode.hpp" #include "utilities/powerOfTwo.hpp" -#include "opto/runtime.hpp" // Portions of code courtesy of Clifford Click diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index 3dd43f12b2f..295f7fca9f1 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -29,18 +29,18 @@ #include "libadt/vectset.hpp" #include "memory/allocation.hpp" #include "memory/resourceArea.hpp" -#include "opto/c2compiler.hpp" #include "opto/arraycopynode.hpp" +#include "opto/c2compiler.hpp" #include "opto/callnode.hpp" +#include "opto/castnode.hpp" #include "opto/cfgnode.hpp" #include "opto/compile.hpp" #include "opto/escape.hpp" -#include "opto/macro.hpp" #include "opto/locknode.hpp" -#include "opto/phaseX.hpp" +#include "opto/macro.hpp" #include "opto/movenode.hpp" #include "opto/narrowptrnode.hpp" -#include "opto/castnode.hpp" +#include "opto/phaseX.hpp" #include "opto/rootnode.hpp" #include "utilities/macros.hpp" diff --git a/src/hotspot/share/opto/gcm.cpp b/src/hotspot/share/opto/gcm.cpp index 6576196268e..8859263d8b6 100644 --- a/src/hotspot/share/opto/gcm.cpp +++ b/src/hotspot/share/opto/gcm.cpp @@ -29,12 +29,12 @@ #include "opto/c2compiler.hpp" #include "opto/callnode.hpp" #include "opto/cfgnode.hpp" +#include "opto/chaitin.hpp" #include "opto/machnode.hpp" #include "opto/opcodes.hpp" #include "opto/phaseX.hpp" #include "opto/rootnode.hpp" #include "opto/runtime.hpp" -#include "opto/chaitin.hpp" #include "runtime/deoptimization.hpp" // Portions of code courtesy of Clifford Click diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 828dff29b55..9c72ec8ac76 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -22,10 +22,10 @@ * */ +#include "asm/register.hpp" +#include "ci/ciObjArray.hpp" #include "ci/ciUtilities.hpp" #include "classfile/javaClasses.hpp" -#include "ci/ciObjArray.hpp" -#include "asm/register.hpp" #include "compiler/compileLog.hpp" #include "gc/shared/barrierSet.hpp" #include "gc/shared/c2/barrierSetC2.hpp" @@ -47,8 +47,8 @@ #include "runtime/deoptimization.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/bitMap.inline.hpp" -#include "utilities/powerOfTwo.hpp" #include "utilities/growableArray.hpp" +#include "utilities/powerOfTwo.hpp" //----------------------------GraphKit----------------------------------------- // Main utility constructor. diff --git a/src/hotspot/share/opto/idealKit.hpp b/src/hotspot/share/opto/idealKit.hpp index 9916701fad7..fe07716dcff 100644 --- a/src/hotspot/share/opto/idealKit.hpp +++ b/src/hotspot/share/opto/idealKit.hpp @@ -26,8 +26,8 @@ #define SHARE_OPTO_IDEALKIT_HPP #include "opto/addnode.hpp" -#include "opto/cfgnode.hpp" #include "opto/castnode.hpp" +#include "opto/cfgnode.hpp" #include "opto/connode.hpp" #include "opto/divnode.hpp" #include "opto/graphKit.hpp" diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index fb048264071..9daf2e6741e 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -32,8 +32,8 @@ #include "opto/loopnode.hpp" #include "opto/phaseX.hpp" #include "opto/predicates_enums.hpp" -#include "opto/runtime.hpp" #include "opto/rootnode.hpp" +#include "opto/runtime.hpp" #include "opto/subnode.hpp" #include "opto/subtypenode.hpp" diff --git a/src/hotspot/share/opto/intrinsicnode.cpp b/src/hotspot/share/opto/intrinsicnode.cpp index 06317a9482c..4f131a39f38 100644 --- a/src/hotspot/share/opto/intrinsicnode.cpp +++ b/src/hotspot/share/opto/intrinsicnode.cpp @@ -22,14 +22,14 @@ * */ -#include "opto/intrinsicnode.hpp" #include "opto/addnode.hpp" -#include "opto/mulnode.hpp" +#include "opto/intrinsicnode.hpp" #include "opto/memnode.hpp" +#include "opto/mulnode.hpp" #include "opto/phaseX.hpp" -#include "utilities/population_count.hpp" #include "utilities/count_leading_zeros.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/population_count.hpp" //============================================================================= // Do not match memory edge. diff --git a/src/hotspot/share/opto/intrinsicnode.hpp b/src/hotspot/share/opto/intrinsicnode.hpp index 3c204f88bc6..df34e363259 100644 --- a/src/hotspot/share/opto/intrinsicnode.hpp +++ b/src/hotspot/share/opto/intrinsicnode.hpp @@ -25,9 +25,9 @@ #ifndef SHARE_OPTO_INTRINSICNODE_HPP #define SHARE_OPTO_INTRINSICNODE_HPP +#include "opto/connode.hpp" #include "opto/node.hpp" #include "opto/opcodes.hpp" -#include "opto/connode.hpp" //----------------------PartialSubtypeCheckNode-------------------------------- diff --git a/src/hotspot/share/opto/lcm.cpp b/src/hotspot/share/opto/lcm.cpp index 0fe246a7679..66ef4b23e2d 100644 --- a/src/hotspot/share/opto/lcm.cpp +++ b/src/hotspot/share/opto/lcm.cpp @@ -31,9 +31,9 @@ #include "opto/c2compiler.hpp" #include "opto/callnode.hpp" #include "opto/cfgnode.hpp" +#include "opto/chaitin.hpp" #include "opto/machnode.hpp" #include "opto/runtime.hpp" -#include "opto/chaitin.hpp" #include "runtime/os.inline.hpp" #include "runtime/sharedRuntime.hpp" diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 6ddb63a9a2d..e454be2b848 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -23,8 +23,8 @@ */ #include "asm/macroAssembler.hpp" -#include "ci/ciUtilities.inline.hpp" #include "ci/ciSymbols.hpp" +#include "ci/ciUtilities.inline.hpp" #include "classfile/vmIntrinsics.hpp" #include "compiler/compileBroker.hpp" #include "compiler/compileLog.hpp" @@ -47,8 +47,8 @@ #include "opto/narrowptrnode.hpp" #include "opto/opaquenode.hpp" #include "opto/parse.hpp" -#include "opto/runtime.hpp" #include "opto/rootnode.hpp" +#include "opto/runtime.hpp" #include "opto/subnode.hpp" #include "opto/vectornode.hpp" #include "prims/jvmtiExport.hpp" diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index 1be08df32ae..136d0979615 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -25,9 +25,9 @@ #include "ci/ciMethod.hpp" #include "classfile/javaClasses.hpp" #include "opto/callGenerator.hpp" -#include "opto/graphKit.hpp" #include "opto/castnode.hpp" #include "opto/convertnode.hpp" +#include "opto/graphKit.hpp" #include "opto/intrinsicnode.hpp" #include "opto/movenode.hpp" diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 96e0fd26d0d..477ea48d419 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -35,6 +35,7 @@ #include "opto/predicates.hpp" #include "opto/rootnode.hpp" #include "opto/subnode.hpp" + #include #include diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 58105afd9d5..afe6a076268 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -33,8 +33,8 @@ #include "opto/convertnode.hpp" #include "opto/divnode.hpp" #include "opto/loopnode.hpp" -#include "opto/mulnode.hpp" #include "opto/movenode.hpp" +#include "opto/mulnode.hpp" #include "opto/opaquenode.hpp" #include "opto/phase.hpp" #include "opto/predicates.hpp" diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index ddeb5f84d49..b33895adf5f 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -30,12 +30,11 @@ #include "opto/callnode.hpp" #include "opto/castnode.hpp" #include "opto/connode.hpp" -#include "opto/castnode.hpp" #include "opto/divnode.hpp" #include "opto/loopnode.hpp" #include "opto/matcher.hpp" -#include "opto/mulnode.hpp" #include "opto/movenode.hpp" +#include "opto/mulnode.hpp" #include "opto/opaquenode.hpp" #include "opto/rootnode.hpp" #include "opto/subnode.hpp" diff --git a/src/hotspot/share/opto/macroArrayCopy.cpp b/src/hotspot/share/opto/macroArrayCopy.cpp index e2209fddbdf..10de940c0c2 100644 --- a/src/hotspot/share/opto/macroArrayCopy.cpp +++ b/src/hotspot/share/opto/macroArrayCopy.cpp @@ -24,14 +24,14 @@ #include "gc/shared/barrierSet.hpp" #include "gc/shared/tlab_globals.hpp" -#include "opto/arraycopynode.hpp" #include "oops/objArrayKlass.hpp" +#include "opto/arraycopynode.hpp" +#include "opto/castnode.hpp" #include "opto/convertnode.hpp" -#include "opto/vectornode.hpp" #include "opto/graphKit.hpp" #include "opto/macro.hpp" #include "opto/runtime.hpp" -#include "opto/castnode.hpp" +#include "opto/vectornode.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/align.hpp" #include "utilities/powerOfTwo.hpp" diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 24b81b894cb..1da8f429359 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -34,7 +34,6 @@ #include "opto/addnode.hpp" #include "opto/arraycopynode.hpp" #include "opto/cfgnode.hpp" -#include "opto/regalloc.hpp" #include "opto/compile.hpp" #include "opto/connode.hpp" #include "opto/convertnode.hpp" @@ -46,6 +45,7 @@ #include "opto/mulnode.hpp" #include "opto/narrowptrnode.hpp" #include "opto/phaseX.hpp" +#include "opto/regalloc.hpp" #include "opto/regmask.hpp" #include "opto/rootnode.hpp" #include "opto/traceMergeStoresTag.hpp" diff --git a/src/hotspot/share/opto/mempointer.cpp b/src/hotspot/share/opto/mempointer.cpp index bede753ff07..e400e40e4a2 100644 --- a/src/hotspot/share/opto/mempointer.cpp +++ b/src/hotspot/share/opto/mempointer.cpp @@ -22,10 +22,10 @@ * */ -#include "opto/mempointer.hpp" +#include "classfile/vmSymbols.hpp" #include "opto/addnode.hpp" +#include "opto/mempointer.hpp" #include "utilities/resourceHash.hpp" -#include "classfile/vmSymbols.hpp" MemPointerParserCallback MemPointerParserCallback::_empty; diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index f0a7b742998..cadc2511770 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -36,8 +36,8 @@ #include "memory/allocation.hpp" #include "opto/ad.hpp" #include "opto/block.hpp" -#include "opto/c2compiler.hpp" #include "opto/c2_MacroAssembler.hpp" +#include "opto/c2compiler.hpp" #include "opto/callnode.hpp" #include "opto/cfgnode.hpp" #include "opto/locknode.hpp" diff --git a/src/hotspot/share/opto/printinlining.cpp b/src/hotspot/share/opto/printinlining.cpp index bd0242e7bf2..be51c08fcfb 100644 --- a/src/hotspot/share/opto/printinlining.cpp +++ b/src/hotspot/share/opto/printinlining.cpp @@ -22,10 +22,10 @@ * */ -#include "opto/printinlining.hpp" -#include "opto/callnode.hpp" #include "memory/allocation.hpp" #include "memory/resourceArea.hpp" +#include "opto/callnode.hpp" +#include "opto/printinlining.hpp" bool InlinePrinter::is_enabled() const { return C->print_intrinsics() || C->print_inlining(); diff --git a/src/hotspot/share/opto/printinlining.hpp b/src/hotspot/share/opto/printinlining.hpp index ae79648319b..57f4b51858e 100644 --- a/src/hotspot/share/opto/printinlining.hpp +++ b/src/hotspot/share/opto/printinlining.hpp @@ -26,9 +26,9 @@ #define PRINTINLINING_HPP #include "memory/allocation.hpp" -#include "utilities/ostream.hpp" -#include "utilities/growableArray.hpp" #include "nmt/nmtTreap.hpp" +#include "utilities/growableArray.hpp" +#include "utilities/ostream.hpp" class JVMState; class ciMethod; diff --git a/src/hotspot/share/opto/rangeinference.hpp b/src/hotspot/share/opto/rangeinference.hpp index 84891d5e311..9bf25245999 100644 --- a/src/hotspot/share/opto/rangeinference.hpp +++ b/src/hotspot/share/opto/rangeinference.hpp @@ -26,6 +26,7 @@ #define SHARE_OPTO_RANGEINFERENCE_HPP #include "utilities/globalDefinitions.hpp" + #include class outputStream; diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index bd84b9dbf24..89b698bfc3f 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -44,8 +44,8 @@ #include "logging/logStream.hpp" #include "memory/oopFactory.hpp" #include "memory/resourceArea.hpp" -#include "oops/objArrayKlass.hpp" #include "oops/klass.inline.hpp" +#include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" #include "opto/ad.hpp" @@ -72,8 +72,8 @@ #include "runtime/synchronizer.hpp" #include "runtime/threadWXSetters.inline.hpp" #include "runtime/vframe.hpp" -#include "runtime/vframeArray.hpp" #include "runtime/vframe_hp.hpp" +#include "runtime/vframeArray.hpp" #include "utilities/copy.hpp" #include "utilities/preserveException.hpp" diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 47735f6bbba..e514535c414 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -25,10 +25,10 @@ #include "opto/castnode.hpp" #include "opto/convertnode.hpp" #include "opto/memnode.hpp" +#include "opto/movenode.hpp" #include "opto/superword.hpp" #include "opto/superwordVTransformBuilder.hpp" #include "opto/vectornode.hpp" -#include "opto/movenode.hpp" SuperWord::SuperWord(const VLoopAnalyzer &vloop_analyzer) : _vloop_analyzer(vloop_analyzer), diff --git a/src/hotspot/share/opto/superwordVTransformBuilder.hpp b/src/hotspot/share/opto/superwordVTransformBuilder.hpp index bff900377f6..ecec380fbfe 100644 --- a/src/hotspot/share/opto/superwordVTransformBuilder.hpp +++ b/src/hotspot/share/opto/superwordVTransformBuilder.hpp @@ -21,8 +21,8 @@ * questions. */ -#include "opto/vtransform.hpp" #include "opto/superword.hpp" +#include "opto/vtransform.hpp" #ifndef SHARE_OPTO_SUPERWORD_VTRANSFORM_BUILDER_HPP #define SHARE_OPTO_SUPERWORD_VTRANSFORM_BUILDER_HPP diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 050297db153..f62eea893cd 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -35,18 +35,18 @@ #include "oops/instanceMirrorKlass.hpp" #include "oops/objArrayKlass.hpp" #include "oops/typeArrayKlass.hpp" -#include "opto/callnode.hpp" #include "opto/arraycopynode.hpp" +#include "opto/callnode.hpp" #include "opto/matcher.hpp" #include "opto/node.hpp" #include "opto/opcodes.hpp" #include "opto/rangeinference.hpp" #include "opto/runtime.hpp" #include "opto/type.hpp" +#include "runtime/stubRoutines.hpp" #include "utilities/checkedCast.hpp" #include "utilities/powerOfTwo.hpp" #include "utilities/stringUtils.hpp" -#include "runtime/stubRoutines.hpp" // Portions of code courtesy of Clifford Click diff --git a/src/hotspot/share/opto/vectorization.hpp b/src/hotspot/share/opto/vectorization.hpp index 9d0887a993f..0af97eb78e4 100644 --- a/src/hotspot/share/opto/vectorization.hpp +++ b/src/hotspot/share/opto/vectorization.hpp @@ -25,10 +25,10 @@ #ifndef SHARE_OPTO_VECTORIZATION_HPP #define SHARE_OPTO_VECTORIZATION_HPP -#include "opto/matcher.hpp" #include "opto/loopnode.hpp" -#include "opto/traceAutoVectorizationTag.hpp" +#include "opto/matcher.hpp" #include "opto/mempointer.hpp" +#include "opto/traceAutoVectorizationTag.hpp" #include "utilities/pair.hpp" // Code in this file and the vectorization.cpp contains shared logics and diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 2b40ca77198..667e74a4761 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -23,12 +23,12 @@ #include "memory/allocation.inline.hpp" #include "opto/connode.hpp" +#include "opto/convertnode.hpp" #include "opto/mulnode.hpp" #include "opto/subnode.hpp" #include "opto/vectornode.hpp" -#include "opto/convertnode.hpp" -#include "utilities/powerOfTwo.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" //------------------------------VectorNode-------------------------------------- diff --git a/src/hotspot/share/opto/vtransform.cpp b/src/hotspot/share/opto/vtransform.cpp index c620b4d8aa6..8a9d4aed13e 100644 --- a/src/hotspot/share/opto/vtransform.cpp +++ b/src/hotspot/share/opto/vtransform.cpp @@ -21,10 +21,10 @@ * questions. */ -#include "opto/vtransform.hpp" -#include "opto/vectornode.hpp" #include "opto/castnode.hpp" #include "opto/convertnode.hpp" +#include "opto/vectornode.hpp" +#include "opto/vtransform.hpp" void VTransformGraph::add_vtnode(VTransformNode* vtnode) { assert(vtnode->_idx == _vtnodes.length(), "position must match idx"); diff --git a/test/hotspot/jtreg/sources/TestIncludesAreSorted.java b/test/hotspot/jtreg/sources/TestIncludesAreSorted.java index 34e8d5be5fd..ed3712810cb 100644 --- a/test/hotspot/jtreg/sources/TestIncludesAreSorted.java +++ b/test/hotspot/jtreg/sources/TestIncludesAreSorted.java @@ -47,6 +47,7 @@ public class TestIncludesAreSorted { "share/ci", "share/compiler", "share/jvmci", + "share/opto" }; /** From c220b1358c91bce2eb7515e9f600004c7b975ee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Maillard?= Date: Mon, 23 Jun 2025 07:52:02 +0000 Subject: [PATCH 134/213] 8356865: C2: Unreasonable values for debug flag FastAllocateSizeLimit can lead to left-shift-overflow, which is UB Reviewed-by: epeter, mhaessig --- src/hotspot/share/opto/graphKit.cpp | 2 + src/hotspot/share/runtime/globals.hpp | 4 ++ .../arguments/TestFastAllocateSizeLimit.java | 58 +++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/arguments/TestFastAllocateSizeLimit.java diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 9c72ec8ac76..02d61596d31 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -3803,6 +3803,8 @@ Node* GraphKit::new_array(Node* klass_node, // array klass (maybe variable) assert(!StressReflectiveCode, "stress mode does not use these paths"); // Increase the size limit if we have exact knowledge of array type. int log2_esize = Klass::layout_helper_log2_element_size(layout_con); + assert(fast_size_limit == 0 || count_leading_zeros(fast_size_limit) > static_cast(LogBytesPerLong - log2_esize), + "fast_size_limit (%d) overflow when shifted left by %d", fast_size_limit, LogBytesPerLong - log2_esize); fast_size_limit <<= (LogBytesPerLong - log2_esize); } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index dc2889e5358..91dadd05180 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1094,9 +1094,13 @@ const int ObjectAlignmentInBytes = 8; develop(bool, CollectIndexSetStatistics, false, \ "Collect information about IndexSets") \ \ + /* This value is later shifted left by up to LogBytesPerLong bits */\ + /* (to convert from element count to size in bytes), so we must ensure */\ + /* it does not overflow during the shift. */\ develop(int, FastAllocateSizeLimit, 128*K, \ /* Note: This value is zero mod 1<<13 for a cheap sparc set. */ \ "Inline allocations larger than this in doublewords must go slow")\ + range(0, (1 << (BitsPerInt - LogBytesPerLong - 1)) - 1) \ \ product_pd(bool, CompactStrings, \ "Enable Strings to use single byte chars in backing store") \ diff --git a/test/hotspot/jtreg/compiler/arguments/TestFastAllocateSizeLimit.java b/test/hotspot/jtreg/compiler/arguments/TestFastAllocateSizeLimit.java new file mode 100644 index 00000000000..d9bbdf3186e --- /dev/null +++ b/test/hotspot/jtreg/compiler/arguments/TestFastAllocateSizeLimit.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @library /test/lib / + * @bug 8356865 + * @key randomness + * @requires vm.flagless & vm.compiler2.enabled & vm.debug == true + * @summary Tests that using reasonable values for -XX:FastAllocateSizeLimit does not crash the VM. + * @run driver compiler.arguments.TestFastAllocateSizeLimit + */ + +package compiler.arguments; + +import java.io.IOException; +import java.util.Random; + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.Utils; + +public class TestFastAllocateSizeLimit { + private static final Random RANDOM = Utils.getRandomInstance(); + + public static void main(String[] args) throws IOException { + if (args.length == 0) { + // range defined in globals.hpp is [0, (1 << (BitsPerInt - LogBytesPerLong - 1)) - 1] + int sizeLimit = RANDOM.nextInt(1 << 28); + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-XX:FastAllocateSizeLimit=" + + sizeLimit, "-Xcomp", "compiler.arguments.TestFastAllocateSizeLimit", "run"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + } else { + System.out.println("Test passed."); + } + } +} From ad1033d68f4dd030cad27f9868d4fa83b5080bcd Mon Sep 17 00:00:00 2001 From: Dingli Zhang Date: Mon, 23 Jun 2025 08:02:40 +0000 Subject: [PATCH 135/213] 8360169: Problem list CodeInvalidationReasonTest.java on linux-riscv64 until JDK-8360168 is fixed Reviewed-by: fyang, fjiang, syan, dnsimon --- test/hotspot/jtreg/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 78f37fd8c6d..f41d8fb64ca 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -66,6 +66,7 @@ compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/NativeCallTest.java 8 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleDebugInfoTest.java 8331704 linux-riscv64 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/SimpleCodeInstallationTest.java 8331704 linux-riscv64 compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/VirtualObjectDebugInfoTest.java 8331704 linux-riscv64 +compiler/jvmci/jdk.vm.ci.code.test/src/jdk/vm/ci/code/test/CodeInvalidationReasonTest.java 8360168 linux-riscv64 compiler/floatingpoint/TestSubnormalFloat.java 8317810 generic-i586 compiler/floatingpoint/TestSubnormalDouble.java 8317810 generic-i586 From 516197f50b079978a4aa1593744cef9d56e01c67 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 23 Jun 2025 08:27:13 +0000 Subject: [PATCH 136/213] 8359924: Deprecate and obsolete ParallelRefProcEnabled Reviewed-by: tschatzl, kbarrett, dholmes --- src/hotspot/share/gc/shared/gc_globals.hpp | 3 ++- src/hotspot/share/runtime/arguments.cpp | 1 + src/java.base/share/man/java.md | 16 ++++++++-------- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index f693ab910ba..903afd58b21 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -199,7 +199,8 @@ range(1, (INT_MAX - 1)) \ \ product(bool, ParallelRefProcEnabled, false, \ - "Enable parallel reference processing whenever possible") \ + "(Deprecated) Enable parallel reference processing " \ + "whenever possible") \ \ product(bool, ParallelRefProcBalancingEnabled, true, \ "Enable balancing of reference processing queues") \ diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 5b56c81a32d..ef588b431e8 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -532,6 +532,7 @@ static SpecialFlag const special_jvm_flags[] = { #ifdef _LP64 { "UseCompressedClassPointers", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::undefined() }, #endif + { "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "CreateMinidumpOnCrash", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::undefined() }, diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index b8c8011eb47..a25ef4100e1 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -2701,14 +2701,6 @@ Java HotSpot VM. > `-XX:ParallelGCThreads=2` -`-XX:+ParallelRefProcEnabled` -: Enables parallel reference processing. By default, collectors employing multiple - threads perform parallel reference processing if the number of parallel threads - to use is larger than one. - The option is available only when the throughput or G1 garbage collector is used - (`-XX:+UseParallelGC` or `-XX:+UseG1GC`). Other collectors employing multiple - threads always perform reference processing in parallel. - `-XX:+PrintAdaptiveSizePolicy` : Enables printing of information about adaptive-generation sizing. By default, this option is disabled. @@ -2904,6 +2896,14 @@ they're used. : Enables the use of Java Flight Recorder (JFR) during the runtime of the application. Since JDK 8u40 this option has not been required to use JFR. +`-XX:+ParallelRefProcEnabled` +: Enables parallel reference processing. By default, collectors employing multiple + threads perform parallel reference processing if the number of parallel threads + to use is larger than one. + The option is available only when the throughput or G1 garbage collector is used + (`-XX:+UseParallelGC` or `-XX:+UseG1GC`). Other collectors employing multiple + threads always perform reference processing in parallel. + ## Obsolete Java Options These `java` options are still accepted but ignored, and a warning is issued From fe7ec312590ed9f70e6caad4ef454123138bbbcf Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Mon, 23 Jun 2025 08:32:02 +0000 Subject: [PATCH 137/213] 8359996: Remove unnecessary List.indexOf key from Track.remove Reviewed-by: aivanov, liach, azvegint --- .../share/classes/javax/sound/midi/Track.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/java.desktop/share/classes/javax/sound/midi/Track.java b/src/java.desktop/share/classes/javax/sound/midi/Track.java index 0de4ccfa6e0..71ff8b0730e 100644 --- a/src/java.desktop/share/classes/javax/sound/midi/Track.java +++ b/src/java.desktop/share/classes/javax/sound/midi/Track.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -198,15 +198,8 @@ public boolean remove(MidiEvent event) { // Or: document that the ticks() length will not be reduced // by deleting events (unless the EOT event is removed) synchronized(eventsList) { - if (set.remove(event)) { - int i = eventsList.indexOf(event); - if (i >= 0) { - eventsList.remove(i); - return true; - } - } + return set.remove(event) && eventsList.remove(event); } - return false; } /** From 251f2ac785708a7ebf713d3fdc7d66317f1b2c2e Mon Sep 17 00:00:00 2001 From: Nikita Gubarkov Date: Mon, 23 Jun 2025 10:52:07 +0000 Subject: [PATCH 138/213] 8355904: Use variadic macros for J2dTrace Reviewed-by: aivanov, serb, prr, avu --- .../java2d/metal/EncoderManager.m | 16 +- .../libawt_lwawt/java2d/metal/MTLBlitLoops.m | 48 ++-- .../libawt_lwawt/java2d/metal/MTLBufImgOps.m | 13 +- .../libawt_lwawt/java2d/metal/MTLClip.m | 9 +- .../libawt_lwawt/java2d/metal/MTLContext.m | 22 +- .../libawt_lwawt/java2d/metal/MTLGlyphCache.m | 28 +-- .../libawt_lwawt/java2d/metal/MTLLayer.m | 6 +- .../libawt_lwawt/java2d/metal/MTLMaskFill.m | 6 +- .../java2d/metal/MTLRenderQueue.h | 10 +- .../java2d/metal/MTLRenderQueue.m | 21 +- .../libawt_lwawt/java2d/metal/MTLRenderer.m | 111 +++++---- .../java2d/metal/MTLSurfaceData.m | 29 ++- .../java2d/metal/MTLTextRenderer.m | 30 ++- .../libawt_lwawt/java2d/metal/MTLTexurePool.m | 9 +- .../java2d/metal/MTLVertexCache.m | 35 +-- .../java2d/opengl/CGLGraphicsConfig.m | 10 +- .../java2d/opengl/CGLSurfaceData.m | 11 +- .../native/common/font/AccelGlyphCache.c | 26 +- .../common/java2d/opengl/OGLBlitLoops.c | 40 +-- .../common/java2d/opengl/OGLBufImgOps.c | 32 +-- .../native/common/java2d/opengl/OGLContext.c | 78 +++--- .../native/common/java2d/opengl/OGLFuncs.h | 4 +- .../native/common/java2d/opengl/OGLMaskFill.c | 8 +- .../native/common/java2d/opengl/OGLPaints.c | 30 +-- .../common/java2d/opengl/OGLRenderQueue.c | 21 +- .../common/java2d/opengl/OGLRenderQueue.h | 6 +- .../native/common/java2d/opengl/OGLRenderer.c | 66 ++--- .../common/java2d/opengl/OGLSurfaceData.c | 57 +++-- .../common/java2d/opengl/OGLTextRenderer.c | 10 +- .../common/java2d/opengl/OGLVertexCache.c | 6 +- .../share/native/libawt/java2d/Trace.h | 120 +-------- .../libawt/java2d/loops/DrawParallelogram.c | 10 +- .../libawt/java2d/pipe/BufferedMaskBlit.c | 26 +- .../libawt/java2d/pipe/BufferedRenderPipe.c | 8 +- .../common/java2d/opengl/GLXGraphicsConfig.c | 30 +-- .../common/java2d/opengl/GLXSurfaceData.c | 6 +- .../native/common/java2d/x11/X11SurfaceData.c | 20 +- .../native/libawt_xawt/awt/awt_GraphicsEnv.c | 24 +- .../native/libawt/java2d/d3d/D3DBlitLoops.cpp | 68 ++--- .../native/libawt/java2d/d3d/D3DBufImgOps.cpp | 14 +- .../native/libawt/java2d/d3d/D3DContext.cpp | 152 ++++++------ .../libawt/java2d/d3d/D3DGlyphCache.cpp | 6 +- .../libawt/java2d/d3d/D3DGraphicsDevice.cpp | 36 +-- .../native/libawt/java2d/d3d/D3DMaskCache.cpp | 8 +- .../native/libawt/java2d/d3d/D3DMaskFill.cpp | 8 +- .../native/libawt/java2d/d3d/D3DPaints.cpp | 6 +- .../native/libawt/java2d/d3d/D3DPipeline.h | 10 +- .../libawt/java2d/d3d/D3DPipelineManager.cpp | 232 +++++++++--------- .../libawt/java2d/d3d/D3DRenderQueue.cpp | 22 +- .../native/libawt/java2d/d3d/D3DRenderer.cpp | 82 +++---- .../libawt/java2d/d3d/D3DResourceManager.cpp | 38 +-- .../native/libawt/java2d/d3d/D3DShaderGen.c | 44 ++-- .../libawt/java2d/d3d/D3DSurfaceData.cpp | 16 +- .../libawt/java2d/d3d/D3DTextRenderer.cpp | 6 +- .../libawt/java2d/d3d/D3DVertexCacher.cpp | 30 +-- .../libawt/java2d/opengl/WGLGraphicsConfig.c | 19 +- .../libawt/java2d/opengl/WGLSurfaceData.c | 12 +- .../libawt/java2d/windows/GDIRenderer.cpp | 102 ++++---- .../java2d/windows/GDIWindowSurfaceData.cpp | 38 +-- .../libawt/java2d/windows/WindowsFlags.cpp | 12 +- .../windows/native/libawt/windows/Devices.cpp | 52 ++-- .../native/libawt/windows/awt_Toolkit.h | 26 +- .../windows/awt_Win32GraphicsDevice.cpp | 36 +-- .../libawt/windows/awt_Win32GraphicsEnv.cpp | 10 +- 64 files changed, 1044 insertions(+), 1083 deletions(-) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m index 95374d2c93e..f9cde966061 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/EncoderManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -361,9 +361,9 @@ - (void)setContext:(MTLContex * _Nonnull)mtlc { jboolean needEnd = JNI_FALSE; if (_encoder != nil) { if (_destination != dest || renderOptions->isAA != _encoderStates.aa) { - J2dTraceLn2(J2D_TRACE_VERBOSE, - "end common encoder because of dest change: %p -> %p", - _destination, dest); + J2dTraceLn(J2D_TRACE_VERBOSE, + "end common encoder because of dest change: %p -> %p", + _destination, dest); needEnd = JNI_TRUE; } else if ((_useStencil == NO) != ([_mtlc.clip isShape] == NO)) { // 1. When mode changes RECT -> SHAPE we must recreate encoder with @@ -374,9 +374,9 @@ - (void)setContext:(MTLContex * _Nonnull)mtlc { // encoder with disabled stencil test, but [encoder // setDepthStencilState:nil] causes crash, so we have to recreate encoder // in such case - J2dTraceLn2(J2D_TRACE_VERBOSE, - "end common encoder because toggle stencil: %d -> %d", - (int)_useStencil, (int)[_mtlc.clip isShape]); + J2dTraceLn(J2D_TRACE_VERBOSE, + "end common encoder because toggle stencil: %d -> %d", + (int)_useStencil, (int)[_mtlc.clip isShape]); needEnd = JNI_TRUE; } } @@ -426,7 +426,7 @@ - (void)setContext:(MTLContex * _Nonnull)mtlc { rpd.stencilAttachment.storeAction = MTLStoreActionStore; } - // J2dTraceLn1(J2D_TRACE_VERBOSE, "created render encoder to draw on + // J2dTraceLn(J2D_TRACE_VERBOSE, "created render encoder to draw on // tex=%p", dest); _encoder = [[cbw getCommandBuffer] renderCommandEncoderWithDescriptor:rpd]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m index 6c91f6a6a13..1a9201f4d6d 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBlitLoops.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,10 +138,10 @@ void drawTex2Tex(MTLContext *mtlc, jdouble dx1, jdouble dy1, jdouble dx2, jdouble dy2) { #ifdef TRACE_drawTex2Tex - J2dRlsTraceLn2(J2D_TRACE_VERBOSE, "drawTex2Tex: src tex=%p, dst tex=%p", src, dst); - J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " sw=%d sh=%d dw=%d dh=%d", src.width, src.height, dst.width, dst.height); - J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", sx1, sy1, sx2, sy2); - J2dRlsTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2); + J2dRlsTraceLn(J2D_TRACE_VERBOSE, "drawTex2Tex: src tex=%p, dst tex=%p", src, dst); + J2dRlsTraceLn(J2D_TRACE_VERBOSE, " sw=%d sh=%d dw=%d dh=%d", src.width, src.height, dst.width, dst.height); + J2dRlsTraceLn(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", sx1, sy1, sx2, sy2); + J2dRlsTraceLn(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2); #endif //TRACE_drawTex2Tex id encoder = [mtlc.encoderManager getTextureEncoder:dst @@ -174,7 +174,7 @@ static void fillSwizzleUniforms(struct SwizzleUniforms *uniforms, const MTLRaste const int dh = MIN(dy2 - dy1, MTL_GPU_FAMILY_MAC_TXT_SIZE); if (dw < sw || dh < sh) { - J2dTraceLn4(J2D_TRACE_ERROR, "replaceTextureRegion: dest size: (%d, %d) less than source size: (%d, %d)", dw, dh, sw, sh); + J2dTraceLn(J2D_TRACE_ERROR, "replaceTextureRegion: dest size: (%d, %d) less than source size: (%d, %d)", dw, dh, sw, sh); return; } @@ -182,8 +182,8 @@ static void fillSwizzleUniforms(struct SwizzleUniforms *uniforms, const MTLRaste raster += (NSUInteger)srcInfo->bounds.y1 * (NSUInteger)srcInfo->scanStride + (NSUInteger)srcInfo->bounds.x1 * (NSUInteger)srcInfo->pixelStride; @autoreleasepool { - J2dTraceLn4(J2D_TRACE_VERBOSE, "replaceTextureRegion src (dw, dh) : [%d, %d] dest (dx1, dy1) =[%d, %d]", - dw, dh, dx1, dy1); + J2dTraceLn(J2D_TRACE_VERBOSE, "replaceTextureRegion src (dw, dh) : [%d, %d] dest (dx1, dy1) =[%d, %d]", + dw, dh, dx1, dy1); id buff = [[mtlc.device newBufferWithLength:(sw * sh * srcInfo->pixelStride) options:MTLResourceStorageModeManaged] autorelease]; // copy src pixels inside src bounds to buff @@ -327,37 +327,37 @@ jboolean clipDestCoords( dcy2 = maxY; if (dcx1 >= dcx2) { - J2dTraceLn2(J2D_TRACE_ERROR, "\tclipDestCoords: dcx1=%1.2f, dcx2=%1.2f", dcx1, dcx2); + J2dTraceLn(J2D_TRACE_ERROR, "\tclipDestCoords: dcx1=%1.2f, dcx2=%1.2f", dcx1, dcx2); dcx1 = dcx2; } if (dcy1 >= dcy2) { - J2dTraceLn2(J2D_TRACE_ERROR, "\tclipDestCoords: dcy1=%1.2f, dcy2=%1.2f", dcy1, dcy2); + J2dTraceLn(J2D_TRACE_ERROR, "\tclipDestCoords: dcy1=%1.2f, dcy2=%1.2f", dcy1, dcy2); dcy1 = dcy2; } } if (*dx2 <= dcx1 || *dx1 >= dcx2 || *dy2 <= dcy1 || *dy1 >= dcy2) { J2dTraceLn(J2D_TRACE_INFO, "\tclipDestCoords: dest rect doesn't intersect clip area"); - J2dTraceLn4(J2D_TRACE_INFO, "\tdx2=%1.4f <= dcx1=%1.4f || *dx1=%1.4f >= dcx2=%1.4f", *dx2, dcx1, *dx1, dcx2); - J2dTraceLn4(J2D_TRACE_INFO, "\t*dy2=%1.4f <= dcy1=%1.4f || *dy1=%1.4f >= dcy2=%1.4f", *dy2, dcy1, *dy1, dcy2); + J2dTraceLn(J2D_TRACE_INFO, "\tdx2=%1.4f <= dcx1=%1.4f || *dx1=%1.4f >= dcx2=%1.4f", *dx2, dcx1, *dx1, dcx2); + J2dTraceLn(J2D_TRACE_INFO, "\t*dy2=%1.4f <= dcy1=%1.4f || *dy1=%1.4f >= dcy2=%1.4f", *dy2, dcy1, *dy1, dcy2); return JNI_FALSE; } if (*dx1 < dcx1) { - J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdx1=%1.2f, will be clipped to %1.2f | sx1+=%d", *dx1, dcx1, (jint)((dcx1 - *dx1) * (sw/dw))); + J2dTraceLn(J2D_TRACE_VERBOSE, "\t\tdx1=%1.2f, will be clipped to %1.2f | sx1+=%d", *dx1, dcx1, (jint)((dcx1 - *dx1) * (sw/dw))); *sx1 += (jint)((dcx1 - *dx1) * (sw/dw)); *dx1 = dcx1; } if (*dx2 > dcx2) { - J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdx2=%1.2f, will be clipped to %1.2f | sx2-=%d", *dx2, dcx2, (jint)((*dx2 - dcx2) * (sw/dw))); + J2dTraceLn(J2D_TRACE_VERBOSE, "\t\tdx2=%1.2f, will be clipped to %1.2f | sx2-=%d", *dx2, dcx2, (jint)((*dx2 - dcx2) * (sw/dw))); *sx2 -= (jint)((*dx2 - dcx2) * (sw/dw)); *dx2 = dcx2; } if (*dy1 < dcy1) { - J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdy1=%1.2f, will be clipped to %1.2f | sy1+=%d", *dy1, dcy1, (jint)((dcy1 - *dy1) * (sh/dh))); + J2dTraceLn(J2D_TRACE_VERBOSE, "\t\tdy1=%1.2f, will be clipped to %1.2f | sy1+=%d", *dy1, dcy1, (jint)((dcy1 - *dy1) * (sh/dh))); *sy1 += (jint)((dcy1 - *dy1) * (sh/dh)); *dy1 = dcy1; } if (*dy2 > dcy2) { - J2dTraceLn3(J2D_TRACE_VERBOSE, "\t\tdy2=%1.2f, will be clipped to %1.2f | sy2-=%d", *dy2, dcy2, (jint)((*dy2 - dcy2) * (sh/dh))); + J2dTraceLn(J2D_TRACE_VERBOSE, "\t\tdy2=%1.2f, will be clipped to %1.2f | sy2-=%d", *dy2, dcy2, (jint)((*dy2 - dcy2) * (sh/dh))); *sy2 -= (jint)((*dy2 - dcy2) * (sh/dh)); *dy2 = dcy2; } @@ -392,7 +392,7 @@ jboolean clipDestCoords( id srcTex = srcOps->pTexture; id dstTex = dstOps->pTexture; if (srcTex == nil || srcTex == nil) { - J2dTraceLn2(J2D_TRACE_ERROR, "MTLBlitLoops_IsoBlit: surface is null (stex=%p, dtex=%p)", srcTex, dstTex); + J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitLoops_IsoBlit: surface is null (stex=%p, dtex=%p)", srcTex, dstTex); return; } @@ -402,7 +402,7 @@ jboolean clipDestCoords( const jdouble dh = dy2 - dy1; if (sw <= 0 || sh <= 0 || dw <= 0 || dh <= 0) { - J2dTraceLn4(J2D_TRACE_WARNING, "MTLBlitLoops_IsoBlit: invalid dimensions: sw=%d, sh%d, dw=%d, dh=%d", sw, sh, dw, dh); + J2dTraceLn(J2D_TRACE_WARNING, "MTLBlitLoops_IsoBlit: invalid dimensions: sw=%d, sh%d, dw=%d, dh=%d", sw, sh, dw, dh); return; } @@ -431,8 +431,8 @@ jboolean clipDestCoords( if (bounds.x2 <= bounds.x1 || bounds.y2 <= bounds.y1) { J2dTraceLn(J2D_TRACE_VERBOSE, "MTLBlitLoops_IsoBlit: source rectangle doesn't intersect with source surface bounds"); - J2dTraceLn6(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d sw=%d sh=%d", sx1, sy1, sx2, sy2, srcOps->width, srcOps->height); - J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2); + J2dTraceLn(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d sw=%d sh=%d", sx1, sy1, sx2, sy2, srcOps->width, srcOps->height); + J2dTraceLn(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", dx1, dy1, dx2, dy2); return; } @@ -521,7 +521,7 @@ jboolean clipDestCoords( return; } if (srctype < 0 || srctype >= sizeof(RasterFormatInfos)/ sizeof(MTLRasterFormatInfo)) { - J2dTraceLn1(J2D_TRACE_ERROR, "MTLBlitLoops_Blit: source pixel format %d isn't supported", srctype); + J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitLoops_Blit: source pixel format %d isn't supported", srctype); return; } const jint sw = sx2 - sx1; @@ -641,14 +641,14 @@ void copyFromMTLBuffer(void *pDst, id srcBuf, NSUInteger offset, NSUI jint srcx, jint srcy, jint dstx, jint dsty, jint width, jint height) { - J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLBlitLoops_SurfaceToSwBlit: sx=%d sy=%d w=%d h=%d dx=%d dy=%d", srcx, srcy, width, height, dstx, dsty); + J2dTraceLn(J2D_TRACE_VERBOSE, "MTLBlitLoops_SurfaceToSwBlit: sx=%d sy=%d w=%d h=%d dx=%d dy=%d", srcx, srcy, width, height, dstx, dsty); BMTLSDOps *srcOps = (BMTLSDOps *)jlong_to_ptr(pSrcOps); SurfaceDataOps *dstOps = (SurfaceDataOps *)jlong_to_ptr(pDstOps); SurfaceDataRasInfo srcInfo, dstInfo; if (dsttype < 0 || dsttype >= sizeof(RasterFormatInfos)/ sizeof(MTLRasterFormatInfo)) { - J2dTraceLn1(J2D_TRACE_ERROR, "MTLBlitLoops_SurfaceToSwBlit: destination pixel format %d isn't supported", dsttype); + J2dTraceLn(J2D_TRACE_ERROR, "MTLBlitLoops_SurfaceToSwBlit: destination pixel format %d isn't supported", dsttype); return; } @@ -736,7 +736,7 @@ void copyFromMTLBuffer(void *pDst, id srcBuf, NSUInteger offset, NSUI // NOTE: using of separate blitCommandBuffer can produce errors (draw into surface (with general cmd-buf) // can be unfinished when reading raster from blit cmd-buf). // Consider to use [mtlc.encoderManager createBlitEncoder] and [mtlc commitCommandBuffer:JNI_TRUE]; - J2dTraceLn1(J2D_TRACE_VERBOSE, "MTLBlitLoops_SurfaceToSwBlit: source texture %p", srcOps->pTexture); + J2dTraceLn(J2D_TRACE_VERBOSE, "MTLBlitLoops_SurfaceToSwBlit: source texture %p", srcOps->pTexture); id cb = [mtlc createCommandBuffer]; id blitEncoder = [cb blitCommandEncoder]; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBufImgOps.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBufImgOps.m index a36e211f748..d34e8761c37 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBufImgOps.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLBufImgOps.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ -(jfloat *) getOffsets { - (id)init:(jboolean)isNonPremult factors:(unsigned char *)factors offsets:(unsigned char *)offsets { self = [super init]; if (self) { - J2dTraceLn1(J2D_TRACE_INFO,"Created MTLRescaleOp: isNonPremult=%d", isNonPremult); + J2dTraceLn(J2D_TRACE_INFO, "Created MTLRescaleOp: isNonPremult=%d", isNonPremult); _isNonPremult = isNonPremult; _normScaleFactors[0] = NEXT_FLOAT(factors); @@ -82,7 +82,9 @@ - (id)init:(jboolean)edgeZeroFill kernelWidth:(jint)kernelWidth device:(id)device { self = [super init]; if (self) { - J2dTraceLn2(J2D_TRACE_INFO,"Created MTLConvolveOp: kernelW=%d kernelH=%d", kernelWidth, kernelHeight); + J2dTraceLn(J2D_TRACE_INFO, + "Created MTLConvolveOp: kernelW=%d kernelH=%d", + kernelWidth, kernelHeight); _isEdgeZeroFill = edgeZeroFill; _kernelSize = kernelWidth * kernelHeight; @@ -142,8 +144,9 @@ - (id)init:(jboolean)nonPremult shortData:(jboolean)shortData device:(id)device { self = [super init]; if (self) { - J2dTraceLn4(J2D_TRACE_INFO,"Created MTLLookupOp: short=%d num=%d len=%d off=%d", - shortData, numBands, bandLength, offset); + J2dTraceLn(J2D_TRACE_INFO, + "Created MTLLookupOp: short=%d num=%d len=%d off=%d", + shortData, numBands, bandLength, offset); _isUseSrcAlpha = numBands != 4; _isNonPremult = nonPremult; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m index 3919d97c53a..3225fc5562c 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLClip.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,14 +128,17 @@ - (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 { } if (x1 >= x2 || y1 >= y2) { - J2dTraceLn4(J2D_TRACE_ERROR, "MTLClip.setClipRect: invalid rect: x1=%d y1=%d x2=%d y2=%d", x1, y1, x2, y2); + J2dTraceLn(J2D_TRACE_ERROR, + "MTLClip.setClipRect: invalid rect: x1=%d y1=%d x2=%d y2=%d", + x1, y1, x2, y2); _clipType = NO_CLIP; } const jint width = x2 - x1; const jint height = y2 - y1; - J2dTraceLn4(J2D_TRACE_INFO, "MTLClip.setClipRect: x=%d y=%d w=%d h=%d", x1, y1, width, height); + J2dTraceLn(J2D_TRACE_INFO, "MTLClip.setClipRect: x=%d y=%d w=%d h=%d", + x1, y1, width, height); _clipRect.x = (NSUInteger)((x1 >= 0) ? x1 : 0); _clipRect.y = (NSUInteger)((y1 >= 0) ? y1 : 0); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m index b88d60957f3..c92f1e21c3a 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLContext.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,7 +251,10 @@ + (MTLContext*) setSurfacesEnv:(JNIEnv*)env src:(jlong)pSrc dst:(jlong)pDst { return NULL; } - J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLContext_SetSurfaces: bsrc=%p (tex=%p type=%d), bdst=%p (tex=%p type=%d)", srcOps, srcOps->pTexture, srcOps->drawableType, dstOps, dstOps->pTexture, dstOps->drawableType); + J2dTraceLn(J2D_TRACE_VERBOSE, + "MTLContext_SetSurfaces: bsrc=%p (tex=%p type=%d), bdst=%p (tex=%p type=%d)", + srcOps, srcOps->pTexture, srcOps->drawableType, + dstOps, dstOps->pTexture, dstOps->drawableType); if (dstOps->drawableType == MTLSD_TEXTURE) { J2dRlsTraceLn(J2D_TRACE_ERROR, @@ -287,7 +290,7 @@ - (void)resetClip { } - (void)setClipRectX1:(jint)x1 Y1:(jint)y1 X2:(jint)x2 Y2:(jint)y2 { - J2dTraceLn4(J2D_TRACE_INFO, "MTLContext.setClipRect: %d,%d - %d,%d", x1, y1, x2, y2); + J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setClipRect: %d,%d - %d,%d", x1, y1, x2, y2); [_clip setClipRectX1:x1 Y1:y1 X2:x2 Y2:y2]; } @@ -316,7 +319,9 @@ - (void)resetComposite { - (void)setAlphaCompositeRule:(jint)rule extraAlpha:(jfloat)extraAlpha flags:(jint)flags { - J2dTraceLn3(J2D_TRACE_INFO, "MTLContext_SetAlphaComposite: rule=%d, extraAlpha=%1.2f, flags=%d", rule, extraAlpha, flags); + J2dTraceLn(J2D_TRACE_INFO, + "MTLContext_SetAlphaComposite: rule=%d, extraAlpha=%1.2f, flags=%d", + rule, extraAlpha, flags); [_composite setRule:rule extraAlpha:extraAlpha]; } @@ -330,7 +335,7 @@ - (NSString*)getPaintDescription { } - (void)setXorComposite:(jint)xp { - J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setXorComposite: xorPixel=%08x", xp); + J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setXorComposite: xorPixel=%08x", xp); [_composite setXORComposite:xp]; } @@ -357,7 +362,10 @@ - (void)resetPaint { } - (void)setColorPaint:(int)pixel { - J2dTraceLn5(J2D_TRACE_INFO, "MTLContext.setColorPaint: pixel=%08x [r=%d g=%d b=%d a=%d]", pixel, (pixel >> 16) & (0xFF), (pixel >> 8) & 0xFF, (pixel) & 0xFF, (pixel >> 24) & 0xFF); + J2dTraceLn(J2D_TRACE_INFO, + "MTLContext.setColorPaint: pixel=%08x [r=%d g=%d b=%d a=%d]", + pixel, (pixel >> 16) & (0xFF), (pixel >> 8) & 0xFF, + (pixel) & 0xFF, (pixel >> 24) & 0xFF); self.paint = [[[MTLColorPaint alloc] initWithColor:pixel] autorelease]; } @@ -452,7 +460,7 @@ - (void)setTexturePaint:(jboolean)useMask return; } - J2dTraceLn1(J2D_TRACE_INFO, "MTLContext.setTexturePaint [tex=%p]", srcOps->pTexture); + J2dTraceLn(J2D_TRACE_INFO, "MTLContext.setTexturePaint [tex=%p]", srcOps->pTexture); self.paint = [[[MTLTexturePaint alloc] initWithUseMask:useMask textureID:srcOps->pTexture diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLGlyphCache.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLGlyphCache.m index 474bdd9af65..1e446967a07 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLGlyphCache.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLGlyphCache.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -269,8 +269,8 @@ { // assert (glyph != NULL && cellInfo != NULL) J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_AddCellInfo"); - J2dTraceLn2(J2D_TRACE_VERBOSE, " glyph 0x%x: adding cell 0x%x to the list", - glyph, cellInfo); + J2dTraceLn(J2D_TRACE_VERBOSE, " glyph 0x%x: adding cell 0x%x to the list", + glyph, cellInfo); cellInfo->glyphInfo = glyph; cellInfo->nextGCI = glyph->cellInfo; @@ -290,9 +290,9 @@ J2dTraceLn(J2D_TRACE_INFO, "MTLGlyphCache_RemoveCellInfo"); do { if (currCellInfo == cellInfo) { - J2dTraceLn2(J2D_TRACE_VERBOSE, - " glyph 0x%x: removing cell 0x%x from glyph's list", - glyph, currCellInfo); + J2dTraceLn(J2D_TRACE_VERBOSE, + " glyph 0x%x: removing cell 0x%x from glyph's list", + glyph, currCellInfo); if (prevInfo == NULL) { // it's the head, chop-chop glyph->cellInfo = currCellInfo->nextGCI; } else { @@ -305,9 +305,9 @@ prevInfo = currCellInfo; currCellInfo = currCellInfo->nextGCI; } while (currCellInfo != NULL); - J2dTraceLn2(J2D_TRACE_WARNING, "MTLGlyphCache_RemoveCellInfo: "\ - "no cell 0x%x in glyph 0x%x's cell list", - cellInfo, glyph); + J2dTraceLn(J2D_TRACE_WARNING, "MTLGlyphCache_RemoveCellInfo: "\ + "no cell 0x%x in glyph 0x%x's cell list", + cellInfo, glyph); } /** @@ -350,15 +350,15 @@ MTLCacheCellInfo *cellInfo = glyph->cellInfo; do { if (cellInfo->cacheInfo == cache) { - J2dTraceLn3(J2D_TRACE_VERBOSE2, - " glyph 0x%x: found cell 0x%x for cache 0x%x", - glyph, cellInfo, cache); + J2dTraceLn(J2D_TRACE_VERBOSE2, + " glyph 0x%x: found cell 0x%x for cache 0x%x", + glyph, cellInfo, cache); return cellInfo; } cellInfo = cellInfo->nextGCI; } while (cellInfo != NULL); } - J2dTraceLn2(J2D_TRACE_VERBOSE2, " glyph 0x%x: no cell for cache 0x%x", - glyph, cache); + J2dTraceLn(J2D_TRACE_VERBOSE2, " glyph 0x%x: no cell for cache 0x%x", + glyph, cache); return NULL; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m index 9f3ab974feb..e153ace3bfd 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLLayer.m @@ -132,9 +132,9 @@ - (void) onScreenWakeup { - (void) blitTexture { if (self.ctx == NULL || self.javaLayer == NULL || self.buffer == nil || self.ctx.device == nil) { - J2dTraceLn4(J2D_TRACE_VERBOSE, - "MTLLayer.blitTexture: uninitialized (mtlc=%p, javaLayer=%p, buffer=%p, device=%p)", self.ctx, - self.javaLayer, self.buffer, ctx.device); + J2dTraceLn(J2D_TRACE_VERBOSE, + "MTLLayer.blitTexture: uninitialized (mtlc=%p, javaLayer=%p, buffer=%p, device=%p)", + self.ctx, self.javaLayer, self.buffer, ctx.device); [self stopDisplayLink]; return; } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskFill.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskFill.m index 89fad174c1e..7d92ae633fa 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskFill.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLMaskFill.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,9 @@ jint maskoff, jint maskscan, jint masklen, unsigned char *pMask) { - J2dTraceLn5(J2D_TRACE_INFO, "MTLMaskFill_MaskFill (x=%d y=%d w=%d h=%d pMask=%p)", x, y, w, h, dstOps->pTexture); + J2dTraceLn(J2D_TRACE_INFO, + "MTLMaskFill_MaskFill (x=%d y=%d w=%d h=%d pMask=%p)", + x, y, w, h, dstOps->pTexture); jint tw, th, x0; jint sx1, sy1, sx2, sy2; jint sx, sy, sw, sh; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.h b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.h index c81770a2bf3..b6330168759 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.h +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,8 +81,8 @@ enum { */ #define ACT_IF_NULL(ACTION, value) \ if ((value) == NULL) { \ - J2dTraceLn1(J2D_TRACE_ERROR, \ - "%s is null", #value); \ + J2dTraceLn(J2D_TRACE_ERROR, \ + "%s is null", #value); \ ACTION; \ } else do { } while (0) #define RETURN_IF_NULL(value) ACT_IF_NULL(return, value) @@ -90,8 +90,8 @@ enum { #define ACT_IF_TRUE(ACTION, value) \ if ((value)) { \ - J2dTraceLn1(J2D_TRACE_ERROR, \ - "%s is false", #value);\ + J2dTraceLn(J2D_TRACE_ERROR, \ + "%s is false", #value); \ ACTION; \ } else do { } while (0) diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m index 257269e647f..3ffa887388e 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderQueue.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,8 +65,8 @@ void MTLRenderQueue_CheckPreviousOp(jint op) { return; } - J2dTraceLn1(J2D_TRACE_VERBOSE, - "MTLRenderQueue_CheckPreviousOp: new op=%d", op); + J2dTraceLn(J2D_TRACE_VERBOSE, + "MTLRenderQueue_CheckPreviousOp: new op=%d", op); switch (mtlPreviousOp) { case MTL_OP_INIT : @@ -104,8 +104,8 @@ void MTLRenderQueue_CheckPreviousOp(jint op) { { unsigned char *b, *end; - J2dTraceLn1(J2D_TRACE_INFO, - "MTLRenderQueue_flushBuffer: limit=%d", limit); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderQueue_flushBuffer: limit=%d", limit); b = (unsigned char *)jlong_to_ptr(buf); if (b == NULL) { @@ -119,9 +119,9 @@ void MTLRenderQueue_CheckPreviousOp(jint op) { while (b < end) { jint opcode = NEXT_INT(b); - J2dTraceLn2(J2D_TRACE_VERBOSE, - "MTLRenderQueue_flushBuffer: opcode=%d, rem=%d", - opcode, (end-b)); + J2dTraceLn(J2D_TRACE_VERBOSE, + "MTLRenderQueue_flushBuffer: opcode=%d, rem=%d", + opcode, (end-b)); switch (opcode) { @@ -868,8 +868,9 @@ void MTLRenderQueue_CheckPreviousOp(jint op) { } default: - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "MTLRenderQueue_flushBuffer: invalid opcode=%d", opcode); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "MTLRenderQueue_flushBuffer: invalid opcode=%d", + opcode); return; } } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderer.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderer.m index 84b76f8c8f3..4d8e0c32f36 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLRenderer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,9 @@ void MTLRenderer_DrawLine(MTLContext *mtlc, BMTLSDOps * dstOps, jint x1, jint y1 return; } - J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_DrawLine (x1=%d y1=%d x2=%d y2=%d), dst tex=%p", x1, y1, x2, y2, dstOps->pTexture); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_DrawLine (x1=%d y1=%d x2=%d y2=%d), dst tex=%p", + x1, y1, x2, y2, dstOps->pTexture); id mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps]; if (mtlEncoder == nil) @@ -138,7 +140,7 @@ void MTLRenderer_DrawPixel(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y) } id dest = dstOps->pTexture; - J2dTraceLn3(J2D_TRACE_INFO, "MTLRenderer_DrawPixel (x=%d y=%d), dst tex=%p", x, y, dest); + J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_DrawPixel (x=%d y=%d), dst tex=%p", x, y, dest); id mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps]; if (mtlEncoder == nil) @@ -160,7 +162,9 @@ void MTLRenderer_DrawRect(MTLContext *mtlc, BMTLSDOps * dstOps, jint x, jint y, } id dest = dstOps->pTexture; - J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_DrawRect (x=%d y=%d w=%d h=%d), dst tex=%p", x, y, w, h, dest); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_DrawRect (x=%d y=%d w=%d h=%d), dst tex=%p", + x, y, w, h, dest); // TODO: use DrawParallelogram(x, y, w, h, lw=1, lh=1) id mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps]; @@ -209,7 +213,9 @@ void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps, return; } - J2dTraceLn4(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: %d points, transX=%d, transY=%d, dst tex=%p", nPoints, transX, transY, dstOps->pTexture); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_DrawPoly: %d points, transX=%d, transY=%d, dst tex=%p", + nPoints, transX, transY, dstOps->pTexture); __block struct { struct Vertex verts[POLYLINE_BUF_SIZE]; @@ -229,20 +235,23 @@ void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps, __block int chunkSize = isLastChunk ? nPoints : POLYLINE_BUF_SIZE; fillVertex(pointsChunk.verts, prevX + transX + 0.5f, prevY + transY + 0.5f); - J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: Point - (%1.2f, %1.2f)", prevX + transX + 0.5f, prevY + transY + 0.5f); + J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: Point - (%1.2f, %1.2f)", + prevX + transX + 0.5f, prevY + transY + 0.5f); for (int i = 1; i < chunkSize; i++) { prevX = *(xPoints++); prevY = *(yPoints++); fillVertex(pointsChunk.verts + i, prevX + transX + 0.5f, prevY + transY + 0.5f); - J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: Point - (%1.2f, %1.2f)", prevX + transX + 0.5f,prevY + transY + 0.5f); + J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: Point - (%1.2f, %1.2f)", + prevX + transX + 0.5f,prevY + transY + 0.5f); } bool drawCloseSegment = false; if (isClosed && isLastChunk) { if (chunkSize + 2 <= POLYLINE_BUF_SIZE) { fillVertex(pointsChunk.verts + chunkSize, firstX + transX + 0.5f, firstY + transY + 0.5f); - J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: Point - (%1.2f, %1.2f)",firstX + transX + 0.5f, firstY + transY + 0.5f); + J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: Point - (%1.2f, %1.2f)", + firstX + transX + 0.5f, firstY + transY + 0.5f); ++chunkSize; } else @@ -263,8 +272,12 @@ void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps, {{firstX + transX + 0.5f, firstY + transY + 0.5f}} }; - J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: last segment Point1 - (%1.2f, %1.2f)",prevX + transX + 0.5f, prevY + transY + 0.5f); - J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawPoly: last segment Point2 - (%1.2f, %1.2f)",firstX + transX + 0.5f, firstY + transY + 0.5f); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_DrawPoly: last segment Point1 - (%1.2f, %1.2f)", + prevX + transX + 0.5f, prevY + transY + 0.5f); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_DrawPoly: last segment Point2 - (%1.2f, %1.2f)", + firstX + transX + 0.5f, firstY + transY + 0.5f); [mtlEncoder setVertexBytes:vertices length:sizeof(vertices) atIndex:MeshVertexBuffer]; [mtlEncoder drawPrimitives:MTLPrimitiveTypeLine vertexStart:0 vertexCount:2]; @@ -324,7 +337,9 @@ void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps, jint scanlineCount, jint *scanlines) { - J2dTraceLn2(J2D_TRACE_INFO, "MTLRenderer_DrawScanlines (scanlineCount=%d), dst tex=%p", scanlineCount, dstOps->pTexture); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_DrawScanlines (scanlineCount=%d), dst tex=%p", + scanlineCount, dstOps->pTexture); if (mtlc == NULL || dstOps == NULL || dstOps->pTexture == NULL) { J2dTraceLn(J2D_TRACE_ERROR, "MTLRenderer_DrawScanlines: dest is null"); return; @@ -332,7 +347,7 @@ void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps, RETURN_IF_NULL(scanlines); int vertexSize = NUM_OF_VERTICES_PER_SCANLINE * scanlineCount * VERTEX_STRUCT_SIZE; - J2dTraceLn1(J2D_TRACE_INFO, "MTLRenderer_DrawScanlines: Total vertex size : %d", vertexSize); + J2dTraceLn(J2D_TRACE_INFO, "MTLRenderer_DrawScanlines: Total vertex size : %d", vertexSize); if (vertexSize == 0) return; id mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps]; @@ -399,8 +414,9 @@ void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps, vertexCount:(remainingScanlineCount / VERTEX_STRUCT_SIZE)]; remainingScanlineCount -= remainingScanlineCount; } - J2dTraceLn1(J2D_TRACE_INFO, - "MTLRenderer_DrawScanlines: Remaining vertex size %d", remainingScanlineCount); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_DrawScanlines: Remaining vertex size %d", + remainingScanlineCount); } while (remainingScanlineCount != 0); } } @@ -424,7 +440,8 @@ void MTLRenderer_DrawPoly(MTLContext *mtlc, BMTLSDOps * dstOps, id dest = dstOps->pTexture; - J2dTraceLn5(J2D_TRACE_INFO, "MTLRenderer_FillRect (x=%d y=%d w=%d h=%d), dst tex=%p", x, y, w, h, dest); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_FillRect (x=%d y=%d w=%d h=%d), dst tex=%p", x, y, w, h, dest); // Encode render command. id mtlEncoder = [mtlc.encoderManager getRenderEncoder:dstOps]; @@ -544,14 +561,14 @@ void MTLRenderer_FillSpans(MTLContext *mtlc, BMTLSDOps * dstOps, jint spanCount, } id dest = dstOps->pTexture; - J2dTraceLn7(J2D_TRACE_INFO, - "MTLRenderer_FillParallelogram" - "(x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f " - "dx2=%6.2f dy2=%6.2f dst tex=%p)", - fx11, fy11, - dx21, dy21, - dx12, dy12, dest); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_FillParallelogram" + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f " + "dx2=%6.2f dy2=%6.2f dst tex=%p)", + fx11, fy11, + dx21, dy21, + dx12, dy12, dest); struct Vertex verts[QUAD_VERTEX_COUNT] = { { {fx11, fy11}}, @@ -589,14 +606,14 @@ void MTLRenderer_FillSpans(MTLContext *mtlc, BMTLSDOps * dstOps, jint spanCount, jfloat ox11 = fx11 - (ldx21 + ldx12) / 2.0f; jfloat oy11 = fy11 - (ldy21 + ldy12) / 2.0f; - J2dTraceLn8(J2D_TRACE_INFO, - "MTLRenderer_DrawParallelogram" - "(x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " - "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", - fx11, fy11, - dx21, dy21, lwr21, - dx12, dy12, lwr12); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_DrawParallelogram" + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " + "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", + fx11, fy11, + dx21, dy21, lwr21, + dx12, dy12, lwr12); // Only need to generate 4 quads if the interior still @@ -790,14 +807,14 @@ void MTLRenderer_FillSpans(MTLContext *mtlc, BMTLSDOps * dstOps, jint spanCount, // parameters for uv texture coordinates of parallelogram corners jfloat ou11, ov11, ou12, ov12, ou21, ov21, ou22, ov22; - J2dTraceLn6(J2D_TRACE_INFO, - "MTLRenderer_FillAAParallelogram " - "(x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f " - "dx2=%6.2f dy2=%6.2f)", - fx11, fy11, - dx21, dy21, - dx12, dy12); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_FillAAParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f " + "dx2=%6.2f dy2=%6.2f)", + fx11, fy11, + dx21, dy21, + dx12, dy12); RETURN_IF_NULL(mtlc); RETURN_IF_NULL(dstOps); @@ -907,14 +924,14 @@ void MTLRenderer_FillSpans(MTLContext *mtlc, BMTLSDOps * dstOps, jint spanCount, // parameters for "inner" parallelogram jfloat ifx11, ify11, idx21, idy21, idx12, idy12; - J2dTraceLn8(J2D_TRACE_INFO, - "MTLRenderer_DrawAAParallelogram " - "(x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " - "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", - fx11, fy11, - dx21, dy21, lwr21, - dx12, dy12, lwr12); + J2dTraceLn(J2D_TRACE_INFO, + "MTLRenderer_DrawAAParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " + "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", + fx11, fy11, + dx21, dy21, lwr21, + dx12, dy12, lwr12); RETURN_IF_NULL(mtlc); RETURN_IF_NULL(dstOps); diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m index f6f6635dacc..fe86b924677 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLSurfaceData.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,9 @@ static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque return JNI_FALSE; } if (width <= 0 || height <= 0) { - J2dRlsTraceLn2(J2D_TRACE_ERROR, "MTLSurfaceData_initTexture: texture dimensions is incorrect, w=%d, h=%d", width, height); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "MTLSurfaceData_initTexture: texture dimensions is incorrect, w=%d, h=%d", + width, height); return JNI_FALSE; } @@ -62,8 +64,9 @@ static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque width = (width <= MTL_GPU_FAMILY_MAC_TXT_SIZE) ? width : 0; height = (height <= MTL_GPU_FAMILY_MAC_TXT_SIZE) ? height : 0; - J2dTraceLn3(J2D_TRACE_VERBOSE, " desired texture dimensions: w=%d h=%d max=%d", - width, height, MTL_GPU_FAMILY_MAC_TXT_SIZE); + J2dTraceLn(J2D_TRACE_VERBOSE, + " desired texture dimensions: w=%d h=%d max=%d", + width, height, MTL_GPU_FAMILY_MAC_TXT_SIZE); // if either dimension is 0, we cannot allocate a texture with the // requested dimensions @@ -93,7 +96,9 @@ static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque bmtlsdo->height = height; bmtlsdo->drawableType = rtt ? MTLSD_RT_TEXTURE : MTLSD_TEXTURE; - J2dTraceLn6(J2D_TRACE_VERBOSE, "MTLSurfaceData_initTexture: w=%d h=%d bp=%p [tex=%p] opaque=%d rtt=%d", width, height, bmtlsdo, bmtlsdo->pTexture, isOpaque, rtt); + J2dTraceLn(J2D_TRACE_VERBOSE, + "MTLSurfaceData_initTexture: w=%d h=%d bp=%p [tex=%p] opaque=%d rtt=%d", + width, height, bmtlsdo, bmtlsdo->pTexture, isOpaque, rtt); return JNI_TRUE; } } @@ -167,7 +172,8 @@ static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque void MTLSD_Delete(JNIEnv *env, BMTLSDOps *bmtlsdo) { - J2dTraceLn3(J2D_TRACE_VERBOSE, "MTLSD_Delete: type=%d %p [tex=%p]", bmtlsdo->drawableType, bmtlsdo, bmtlsdo->pTexture); + J2dTraceLn(J2D_TRACE_VERBOSE, "MTLSD_Delete: type=%d %p [tex=%p]", + bmtlsdo->drawableType, bmtlsdo, bmtlsdo->pTexture); if (bmtlsdo->drawableType == MTLSD_WINDOW) { bmtlsdo->drawableType = MTLSD_UNDEFINED; } else if ( @@ -275,7 +281,8 @@ static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque bmtlsdo->height = surfaceBounds.size.height; JNI_COCOA_EXIT(env); - J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", bmtlsdo->width, bmtlsdo->height); + J2dTraceLn(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", + bmtlsdo->width, bmtlsdo->height); return JNI_TRUE; } @@ -301,10 +308,10 @@ static jboolean MTLSurfaceData_initTexture(BMTLSDOps *bmtlsdo, jboolean isOpaque return; } - J2dTraceLn1(J2D_TRACE_INFO, "MTLSurfaceData_initOps p=%p", bmtlsdo); - J2dTraceLn1(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData)); - J2dTraceLn1(J2D_TRACE_INFO, " layerPtr=%p", jlong_to_ptr(layerPtr)); - J2dTraceLn2(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff); + J2dTraceLn(J2D_TRACE_INFO, "MTLSurfaceData_initOps p=%p", bmtlsdo); + J2dTraceLn(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData)); + J2dTraceLn(J2D_TRACE_INFO, " layerPtr=%p", jlong_to_ptr(layerPtr)); + J2dTraceLn(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff); gc = (*env)->NewGlobalRef(env, gc); if (gc == NULL) { diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m index a52d32a5dea..b57e384b37e 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTextRenderer.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -263,8 +263,8 @@ jfloat clr[4]; jint col = cPaint.color; - J2dTraceLn2(J2D_TRACE_INFO, "primary color %x, contrast %d", col, contrast); - J2dTraceLn2(J2D_TRACE_INFO, "gamma %f, invgamma %f", gamma, invgamma); + J2dTraceLn(J2D_TRACE_INFO, "primary color %x, contrast %d", col, contrast); + J2dTraceLn(J2D_TRACE_INFO, "gamma %f, invgamma %f", gamma, invgamma); clr[0] = ((col >> 16) & 0xFF)/255.0f; clr[1] = ((col >> 8) & 0xFF)/255.0f; @@ -439,8 +439,8 @@ static void DisableColorGlyphPainting(MTLContext *mtlc) { tx2 = cell->tx2; ty2 = cell->ty2; - J2dTraceLn4(J2D_TRACE_INFO, "tx1 = %f, ty1 = %f, tx2 = %f, ty2 = %f", tx1, ty1, tx2, ty2); - J2dTraceLn2(J2D_TRACE_INFO, "width = %d height = %d", dstOps->width, dstOps->height); + J2dTraceLn(J2D_TRACE_INFO, "tx1 = %f, ty1 = %f, tx2 = %f, ty2 = %f", tx1, ty1, tx2, ty2); + J2dTraceLn(J2D_TRACE_INFO, "width = %d height = %d", dstOps->width, dstOps->height); LCD_ADD_TRIANGLES(tx1, ty1, tx2, ty2, x, y, x+w, y+h); @@ -490,7 +490,9 @@ static void DisableColorGlyphPainting(MTLContext *mtlc) { for (sx = 0; sx < w; sx += tw, x += tw) { sw = ((sx + tw) > w) ? (w - sx) : tw; - J2dTraceLn7(J2D_TRACE_INFO, "sx = %d sy = %d x = %d y = %d sw = %d sh = %d w = %d", sx, sy, x, y, sw, sh, w); + J2dTraceLn(J2D_TRACE_INFO, + "sx = %d sy = %d x = %d y = %d sw = %d sh = %d w = %d", + sx, sy, x, y, sw, sh, w); MTLVertexCache_AddMaskQuad(mtlc, sx, sy, x, y, sw, sh, w, ginfo->image, @@ -514,8 +516,10 @@ static void DisableColorGlyphPainting(MTLContext *mtlc) { jint h = ginfo->height; id blitTexture = nil; - J2dTraceLn2(J2D_TRACE_INFO, "MTLTR_DrawLCDGlyphNoCache x %d, y%d", x, y); - J2dTraceLn3(J2D_TRACE_INFO, "MTLTR_DrawLCDGlyphNoCache rowBytesOffset=%d, rgbOrder=%d, contrast=%d", rowBytesOffset, rgbOrder, contrast); + J2dTraceLn(J2D_TRACE_INFO, "MTLTR_DrawLCDGlyphNoCache x %d, y%d", x, y); + J2dTraceLn(J2D_TRACE_INFO, + "MTLTR_DrawLCDGlyphNoCache rowBytesOffset=%d, rgbOrder=%d, contrast=%d", + rowBytesOffset, rgbOrder, contrast); id encoder = nil; @@ -578,7 +582,9 @@ static void DisableColorGlyphPainting(MTLContext *mtlc) { tx2 = 1.0f; ty2 = 1.0f; - J2dTraceLn2(J2D_TRACE_INFO, "MTLTR_DrawLCDGlyphNoCache : dstOps->width = %d, dstOps->height = %d", dstOps->width, dstOps->height); + J2dTraceLn(J2D_TRACE_INFO, + "MTLTR_DrawLCDGlyphNoCache : dstOps->width = %d, dstOps->height = %d", + dstOps->width, dstOps->height); LCD_ADD_TRIANGLES(tx1, ty1, tx2, ty2, x, y, x+w, y+h); @@ -673,7 +679,7 @@ static void DisableColorGlyphPainting(MTLContext *mtlc) { } glyphMode = MODE_NOT_INITED; - J2dTraceLn1(J2D_TRACE_INFO, "totalGlyphs = %d", totalGlyphs); + J2dTraceLn(J2D_TRACE_INFO, "totalGlyphs = %d", totalGlyphs); jboolean flushBeforeLCD = JNI_FALSE; for (glyphCounter = 0; glyphCounter < totalGlyphs; glyphCounter++) { @@ -711,8 +717,8 @@ static void DisableColorGlyphPainting(MTLContext *mtlc) { continue; } - J2dTraceLn2(J2D_TRACE_INFO, "Glyph width = %d height = %d", ginfo->width, ginfo->height); - J2dTraceLn1(J2D_TRACE_INFO, "rowBytes = %d", ginfo->rowBytes); + J2dTraceLn(J2D_TRACE_INFO, "Glyph width = %d height = %d", ginfo->width, ginfo->height); + J2dTraceLn(J2D_TRACE_INFO, "rowBytes = %d", ginfo->rowBytes); if (ginfo->rowBytes == ginfo->width) { // grayscale or monochrome glyph data if (ginfo->width <= MTLTR_CACHE_CELL_WIDTH && diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTexurePool.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTexurePool.m index 87c489fd11d..b9ec4263024 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTexurePool.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLTexurePool.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -371,7 +371,8 @@ - (MTLPooledTextureHandle *) getTexture:(int)width height:(int)height format:(MT const int newCellHeight = cellY1 <= _poolCellHeight ? _poolCellHeight : cellY1; const int newCellsCount = newCellWidth*newCellHeight; #ifdef DEBUG - J2dTraceLn2(J2D_TRACE_VERBOSE, "MTLTexturePool: resize: %d -> %d", _poolCellWidth * _poolCellHeight, newCellsCount); + J2dTraceLn(J2D_TRACE_VERBOSE, "MTLTexturePool: resize: %d -> %d", + _poolCellWidth * _poolCellHeight, newCellsCount); #endif void ** newcells = malloc(newCellsCount*sizeof(void*)); const int strideBytes = _poolCellWidth * sizeof(void*); @@ -425,7 +426,9 @@ - (MTLPooledTextureHandle *) getTexture:(int)width height:(int)height format:(MT } minDeltaTpi = [cell createItem:device width:width height:height format:format isMultiSample:isMultiSample]; _memoryTotalAllocated += requestedBytes; - J2dTraceLn5(J2D_TRACE_VERBOSE, "MTLTexturePool: created pool item: tex=%p, w=%d h=%d, pf=%d | total memory = %d Kb", minDeltaTpi.texture, width, height, format, _memoryTotalAllocated/1024); + J2dTraceLn(J2D_TRACE_VERBOSE, "MTLTexturePool: created pool item: "\ + "tex=%p, w=%d h=%d, pf=%d | total memory = %d Kb", + minDeltaTpi.texture, width, height, format, _memoryTotalAllocated/1024); } minDeltaTpi.isBusy = YES; diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m index 61870120ed3..e94ea306c47 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/metal/MTLVertexCache.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,8 +95,9 @@ atIndex:MeshVertexBuffer]; [encoder setFragmentTexture:maskCacheTex.texture atIndex: 0]; - J2dTraceLn1(J2D_TRACE_INFO, - "MTLVertexCache_FlushVertexCache : encode %d characters", (vertexCacheIndex / 6)); + J2dTraceLn(J2D_TRACE_INFO, + "MTLVertexCache_FlushVertexCache : encode %d characters", + (vertexCacheIndex / 6)); [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:vertexCacheIndex]; } vertexCacheIndex = 0; @@ -119,8 +120,9 @@ atIndex:MeshVertexBuffer]; id glyphCacheTex = MTLTR_GetGlyphCacheTexture(); [encoder setFragmentTexture:glyphCacheTex atIndex: 0]; - J2dTraceLn1(J2D_TRACE_INFO, - "MTLVertexCache_FlushGlyphVertexCache : encode %d characters", (vertexCacheIndex / 6)); + J2dTraceLn(J2D_TRACE_INFO, + "MTLVertexCache_FlushGlyphVertexCache : encode %d characters", + (vertexCacheIndex / 6)); [encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:vertexCacheIndex]; } vertexCacheIndex = 0; @@ -220,8 +222,8 @@ void MTLVertexCache_FreeVertexCache() jfloat tx1, ty1, tx2, ty2; jfloat dx1, dy1, dx2, dy2; - J2dTraceLn1(J2D_TRACE_INFO, "MTLVertexCache_AddMaskQuad: %d", - maskCacheIndex); + J2dTraceLn(J2D_TRACE_INFO, "MTLVertexCache_AddMaskQuad: %d", + maskCacheIndex); // MTLVC_ADD_TRIANGLES at the end of this function // will place VERTS_FOR_A_QUAD vertexes to the vertex cache @@ -229,7 +231,8 @@ void MTLVertexCache_FreeVertexCache() if ((maskCacheIndex >= MTLVC_MASK_CACHE_MAX_INDEX) || ((vertexCacheIndex + VERTS_FOR_A_QUAD) >= MTLVC_MAX_INDEX)) { - J2dTraceLn2(J2D_TRACE_INFO, "maskCacheIndex = %d, vertexCacheIndex = %d", maskCacheIndex, vertexCacheIndex); + J2dTraceLn(J2D_TRACE_INFO, "maskCacheIndex = %d, vertexCacheIndex = %d", + maskCacheIndex, vertexCacheIndex); MTLVertexCache_FlushVertexCache(mtlc); MTLVertexCache_EnableMaskCache(mtlc, dstOps); maskCacheIndex = 0; @@ -240,8 +243,9 @@ void MTLVertexCache_FreeVertexCache() (maskCacheIndex % MTLVC_MASK_CACHE_WIDTH_IN_TILES); jint texy = MTLVC_MASK_CACHE_TILE_HEIGHT * (maskCacheIndex / MTLVC_MASK_CACHE_WIDTH_IN_TILES); - J2dTraceLn5(J2D_TRACE_INFO, "texx = %d texy = %d width = %d height = %d maskscan = %d", texx, texy, width, - height, maskscan); + J2dTraceLn(J2D_TRACE_INFO, + "texx = %d texy = %d width = %d height = %d maskscan = %d", + texx, texy, width, height, maskscan); NSUInteger bytesPerRow = 1 * width; NSUInteger slice = bytesPerRow * srcy + srcx; MTLRegion region = { @@ -271,9 +275,9 @@ void MTLVertexCache_FreeVertexCache() char tile[size]; dst_offset = 0; for (int i = srcy; i < srcy + height; i++) { - J2dTraceLn2(J2D_TRACE_INFO, "srcx = %d srcy = %d", srcx, srcy); + J2dTraceLn(J2D_TRACE_INFO, "srcx = %d srcy = %d", srcx, srcy); src_offset = maskscan * i + srcx; - J2dTraceLn2(J2D_TRACE_INFO, "src_offset = %d dst_offset = %d", src_offset, dst_offset); + J2dTraceLn(J2D_TRACE_INFO, "src_offset = %d dst_offset = %d", src_offset, dst_offset); memcpy(tile + dst_offset, mask + src_offset, width); dst_offset = dst_offset + width; } @@ -301,7 +305,9 @@ void MTLVertexCache_FreeVertexCache() dx2 = dx1 + width; dy2 = dy1 + height; - J2dTraceLn8(J2D_TRACE_INFO, "tx1 = %f ty1 = %f tx2 = %f ty2 = %f dx1 = %f dy1 = %f dx2 = %f dy2 = %f", tx1, ty1, tx2, ty2, dx1, dy1, dx2, dy2); + J2dTraceLn(J2D_TRACE_INFO, + "tx1 = %f ty1 = %f tx2 = %f ty2 = %f dx1 = %f dy1 = %f dx2 = %f dy2 = %f", + tx1, ty1, tx2, ty2, dx1, dy1, dx2, dy2); MTLVC_ADD_TRIANGLES(tx1, ty1, tx2, ty2, dx1, dy1, dx2, dy2); } @@ -317,7 +323,8 @@ void MTLVertexCache_FreeVertexCache() // so need to check space for VERTS_FOR_A_QUAD elements if ((vertexCacheIndex + VERTS_FOR_A_QUAD) >= MTLVC_MAX_INDEX) { - J2dTraceLn2(J2D_TRACE_INFO, "maskCacheIndex = %d, vertexCacheIndex = %d", maskCacheIndex, vertexCacheIndex); + J2dTraceLn(J2D_TRACE_INFO, "maskCacheIndex = %d, vertexCacheIndex = %d", + maskCacheIndex, vertexCacheIndex); MTLVertexCache_FlushGlyphVertexCache(); } diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m index 9ffaba58c02..ff512247e20 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLGraphicsConfig.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -220,7 +220,7 @@ [NSOpenGLContext clearCurrentContext]; return; } - J2dRlsTraceLn1(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL version=%s", versionstr); + J2dRlsTraceLn(J2D_TRACE_INFO, "CGLGraphicsConfig_getCGLConfigInfo: OpenGL version=%s", versionstr); jint caps = CAPS_EMPTY; OGLContext_GetExtensionInfo(env, &caps); @@ -234,9 +234,9 @@ caps |= CAPS_DOUBLEBUFFERED; } - J2dRlsTraceLn1(J2D_TRACE_INFO, - "CGLGraphicsConfig_getCGLConfigInfo: db=%d", - (caps & CAPS_DOUBLEBUFFERED) != 0); + J2dRlsTraceLn(J2D_TRACE_INFO, + "CGLGraphicsConfig_getCGLConfigInfo: db=%d", + (caps & CAPS_DOUBLEBUFFERED) != 0); // remove before shipping (?) #if 1 diff --git a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m index b90d4ff00ea..e9aac4de7fe 100644 --- a/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m +++ b/src/java.desktop/macosx/native/libawt_lwawt/java2d/opengl/CGLSurfaceData.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -199,7 +199,8 @@ extern CGLError CGLTexImageIOSurface2D( CGLSDOps *dstCGLOps = (CGLSDOps *)dstOps->privOps; - J2dTraceLn4(J2D_TRACE_VERBOSE, " src: %d %p dst: %d %p", srcOps->drawableType, srcOps, dstOps->drawableType, dstOps); + J2dTraceLn(J2D_TRACE_VERBOSE, " src: %d %p dst: %d %p", + srcOps->drawableType, srcOps, dstOps->drawableType, dstOps); OGLContext *oglc = dstCGLOps->configInfo->context; if (oglc == NULL) { @@ -292,7 +293,7 @@ extern CGLError CGLTexImageIOSurface2D( oglsdo->height = surfaceBounds.size.height; JNI_COCOA_EXIT(env); - J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", oglsdo->width, oglsdo->height); + J2dTraceLn(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", oglsdo->width, oglsdo->height); return JNI_TRUE; } @@ -338,8 +339,8 @@ extern CGLError CGLTexImageIOSurface2D( jint xoff, jint yoff, jboolean isOpaque) { J2dTraceLn(J2D_TRACE_INFO, "CGLSurfaceData_initOps"); - J2dTraceLn1(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData)); - J2dTraceLn2(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff); + J2dTraceLn(J2D_TRACE_INFO, " pPeerData=%p", jlong_to_ptr(pPeerData)); + J2dTraceLn(J2D_TRACE_INFO, " xoff=%d, yoff=%d", (int)xoff, (int)yoff); gc = (*env)->NewGlobalRef(env, gc); if (gc == NULL) { diff --git a/src/java.desktop/share/native/common/font/AccelGlyphCache.c b/src/java.desktop/share/native/common/font/AccelGlyphCache.c index 67729ad7ec3..37ca924a78e 100644 --- a/src/java.desktop/share/native/common/font/AccelGlyphCache.c +++ b/src/java.desktop/share/native/common/font/AccelGlyphCache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -319,8 +319,8 @@ AccelGlyphCache_AddCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo) { // assert (glyph != NULL && cellInfo != NULL) J2dTraceLn(J2D_TRACE_INFO, "AccelGlyphCache_AddCellInfo"); - J2dTraceLn2(J2D_TRACE_VERBOSE, " glyph 0x%x: adding cell 0x%x to the list", - glyph, cellInfo); + J2dTraceLn(J2D_TRACE_VERBOSE, " glyph 0x%x: adding cell 0x%x to the list", + glyph, cellInfo); cellInfo->glyphInfo = glyph; cellInfo->nextGCI = glyph->cellInfo; @@ -340,8 +340,8 @@ AccelGlyphCache_RemoveCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo) J2dTraceLn(J2D_TRACE_INFO, "AccelGlyphCache_RemoveCellInfo"); do { if (currCellInfo == cellInfo) { - J2dTraceLn2(J2D_TRACE_VERBOSE, - " glyph 0x%x: removing cell 0x%x from glyph's list", + J2dTraceLn(J2D_TRACE_VERBOSE, + " glyph 0x%x: removing cell 0x%x from glyph's list", glyph, currCellInfo); if (prevInfo == NULL) { // it's the head, chop-chop glyph->cellInfo = currCellInfo->nextGCI; @@ -355,9 +355,9 @@ AccelGlyphCache_RemoveCellInfo(GlyphInfo *glyph, CacheCellInfo *cellInfo) prevInfo = currCellInfo; currCellInfo = currCellInfo->nextGCI; } while (currCellInfo != NULL); - J2dTraceLn2(J2D_TRACE_WARNING, "AccelGlyphCache_RemoveCellInfo: "\ - "no cell 0x%x in glyph 0x%x's cell list", - cellInfo, glyph); + J2dTraceLn(J2D_TRACE_WARNING, "AccelGlyphCache_RemoveCellInfo: "\ + "no cell 0x%x in glyph 0x%x's cell list", + cellInfo, glyph); } /** @@ -400,16 +400,16 @@ AccelGlyphCache_GetCellInfoForCache(GlyphInfo *glyph, GlyphCacheInfo *cache) CacheCellInfo *cellInfo = glyph->cellInfo; do { if (cellInfo->cacheInfo == cache) { - J2dTraceLn3(J2D_TRACE_VERBOSE2, - " glyph 0x%x: found cell 0x%x for cache 0x%x", - glyph, cellInfo, cache); + J2dTraceLn(J2D_TRACE_VERBOSE2, + " glyph 0x%x: found cell 0x%x for cache 0x%x", + glyph, cellInfo, cache); return cellInfo; } cellInfo = cellInfo->nextGCI; } while (cellInfo != NULL); } - J2dTraceLn2(J2D_TRACE_VERBOSE2, " glyph 0x%x: no cell for cache 0x%x", - glyph, cache); + J2dTraceLn(J2D_TRACE_VERBOSE2, " glyph 0x%x: no cell for cache 0x%x", + glyph, cache); return NULL; } diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLBlitLoops.c b/src/java.desktop/share/native/common/java2d/opengl/OGLBlitLoops.c index 8e577e11788..d2579f7b653 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLBlitLoops.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLBlitLoops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -497,11 +497,11 @@ OGLBlitLoops_IsoBlit(JNIEnv *env, sy2 = srcInfo.bounds.y2; } - J2dTraceLn2(J2D_TRACE_VERBOSE, " texture=%d hint=%d", texture, hint); - J2dTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", - sx1, sy1, sx2, sy2); - J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", - dx1, dy1, dx2, dy2); + J2dTraceLn(J2D_TRACE_VERBOSE, " texture=%d hint=%d", texture, hint); + J2dTraceLn(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", + sx1, sy1, sx2, sy2); + J2dTraceLn(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", + dx1, dy1, dx2, dy2); if (texture) { GLint glhint = (hint == OGLSD_XFORM_BILINEAR) ? GL_LINEAR : @@ -625,12 +625,12 @@ OGLBlitLoops_Blit(JNIEnv *env, sy2 = srcInfo.bounds.y2; } - J2dTraceLn3(J2D_TRACE_VERBOSE, " texture=%d srctype=%d hint=%d", - texture, srctype, hint); - J2dTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", - sx1, sy1, sx2, sy2); - J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", - dx1, dy1, dx2, dy2); + J2dTraceLn(J2D_TRACE_VERBOSE, " texture=%d srctype=%d hint=%d", + texture, srctype, hint); + J2dTraceLn(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", + sx1, sy1, sx2, sy2); + J2dTraceLn(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", + dx1, dy1, dx2, dy2); // Note: we will calculate x/y positions in the raster manually j2d_glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); @@ -821,10 +821,10 @@ OGLBlitLoops_SurfaceToSwBlit(JNIEnv *env, OGLContext *oglc, } #endif - J2dTraceLn4(J2D_TRACE_VERBOSE, " sx=%d sy=%d w=%d h=%d", - srcx, srcy, width, height); - J2dTraceLn2(J2D_TRACE_VERBOSE, " dx=%d dy=%d", - dstx, dsty); + J2dTraceLn(J2D_TRACE_VERBOSE, " sx=%d sy=%d w=%d h=%d", + srcx, srcy, width, height); + J2dTraceLn(J2D_TRACE_VERBOSE, " dx=%d dy=%d", + dstx, dsty); // this accounts for lower-left origin of the source region srcx = srcOps->xOffset + srcx; @@ -864,10 +864,10 @@ OGLBlitLoops_CopyArea(JNIEnv *env, RETURN_IF_NULL(dstOps); RESET_PREVIOUS_OP(); - J2dTraceLn4(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", - x, y, width, height); - J2dTraceLn2(J2D_TRACE_VERBOSE, " dx=%d dy=%d", - dx, dy); + J2dTraceLn(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", + x, y, width, height); + J2dTraceLn(J2D_TRACE_VERBOSE, " dx=%d dy=%d", + dx, dy); srcBounds.x1 = x; srcBounds.y1 = y; diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLBufImgOps.c b/src/java.desktop/share/native/common/java2d/opengl/OGLBufImgOps.c index b1b216287a5..ee08b4cd600 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLBufImgOps.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLBufImgOps.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,9 +135,9 @@ OGLBufImgOps_CreateConvolveProgram(jint flags) char edge[100]; char finalSource[2000]; - J2dTraceLn1(J2D_TRACE_INFO, - "OGLBufImgOps_CreateConvolveProgram: flags=%d", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "OGLBufImgOps_CreateConvolveProgram: flags=%d", + flags); if (IS_SET(CONVOLVE_EDGE_ZERO_FILL)) { // EDGE_ZERO_FILL: fill in zero at the edges @@ -189,9 +189,9 @@ OGLBufImgOps_EnableConvolveOp(OGLContext *oglc, jlong pSrcOps, GLint loc; jint flags = 0; - J2dTraceLn2(J2D_TRACE_INFO, - "OGLBufImgOps_EnableConvolveOp: kernelW=%d kernelH=%d", - kernelWidth, kernelHeight); + J2dTraceLn(J2D_TRACE_INFO, + "OGLBufImgOps_EnableConvolveOp: kernelW=%d kernelH=%d", + kernelWidth, kernelHeight); RETURN_IF_NULL(oglc); RETURN_IF_NULL(srcOps); @@ -350,9 +350,9 @@ OGLBufImgOps_CreateRescaleProgram(jint flags) char *postRescale = ""; char finalSource[2000]; - J2dTraceLn1(J2D_TRACE_INFO, - "OGLBufImgOps_CreateRescaleProgram: flags=%d", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "OGLBufImgOps_CreateRescaleProgram: flags=%d", + flags); if (IS_SET(RESCALE_NON_PREMULT)) { preRescale = "srcColor.rgb /= srcColor.a;"; @@ -572,9 +572,9 @@ OGLBufImgOps_CreateLookupProgram(jint flags) char *postLookup = ""; char finalSource[2000]; - J2dTraceLn1(J2D_TRACE_INFO, - "OGLBufImgOps_CreateLookupProgram: flags=%d", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "OGLBufImgOps_CreateLookupProgram: flags=%d", + flags); if (IS_SET(LOOKUP_USE_SRC_ALPHA)) { // when numComps is 1 or 3, the alpha is not looked up in the table; @@ -632,9 +632,9 @@ OGLBufImgOps_EnableLookupOp(OGLContext *oglc, jlong pSrcOps, int i; jint flags = 0; - J2dTraceLn4(J2D_TRACE_INFO, - "OGLBufImgOps_EnableLookupOp: short=%d num=%d len=%d off=%d", - shortData, numBands, bandLength, offset); + J2dTraceLn(J2D_TRACE_INFO, + "OGLBufImgOps_EnableLookupOp: short=%d num=%d len=%d off=%d", + shortData, numBands, bandLength, offset); for (i = 0; i < 4; i++) { bands[i] = NULL; diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLContext.c b/src/java.desktop/share/native/common/java2d/opengl/OGLContext.c index 89c3af32b1d..8e1211bda95 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLContext.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLContext.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,11 +87,11 @@ OGLContext_SetViewport(OGLSDOps *srcOps, OGLSDOps *dstOps) jint width = dstOps->width; jint height = dstOps->height; - J2dTraceLn4(J2D_TRACE_INFO, - "OGLContext_SetViewport: w=%d h=%d read=%s draw=%s", - width, height, - OGLC_ACTIVE_BUFFER_NAME(srcOps->activeBuffer), - OGLC_ACTIVE_BUFFER_NAME(dstOps->activeBuffer)); + J2dTraceLn(J2D_TRACE_INFO, + "OGLContext_SetViewport: w=%d h=%d read=%s draw=%s", + width, height, + OGLC_ACTIVE_BUFFER_NAME(srcOps->activeBuffer), + OGLC_ACTIVE_BUFFER_NAME(dstOps->activeBuffer)); // set the viewport and projection matrix j2d_glViewport(dstOps->xOffset, dstOps->yOffset, @@ -162,8 +162,8 @@ OGLContext_SetSurfaces(JNIEnv *env, jlong pSrc, jlong pDst) return NULL; } - J2dTraceLn2(J2D_TRACE_VERBOSE, " srctype=%d dsttype=%d", - srcOps->drawableType, dstOps->drawableType); + J2dTraceLn(J2D_TRACE_VERBOSE, " srctype=%d dsttype=%d", + srcOps->drawableType, dstOps->drawableType); if (dstOps->drawableType == OGLSD_TEXTURE) { J2dRlsTraceLn(J2D_TRACE_ERROR, @@ -230,9 +230,9 @@ OGLContext_SetRectClip(OGLContext *oglc, OGLSDOps *dstOps, jint width = x2 - x1; jint height = y2 - y1; - J2dTraceLn4(J2D_TRACE_INFO, - "OGLContext_SetRectClip: x=%d y=%d w=%d h=%d", - x1, y1, width, height); + J2dTraceLn(J2D_TRACE_INFO, + "OGLContext_SetRectClip: x=%d y=%d w=%d h=%d", + x1, y1, width, height); RETURN_IF_NULL(dstOps); RETURN_IF_NULL(oglc); @@ -335,7 +335,7 @@ OGLContext_EndShapeClip(OGLContext *oglc, OGLSDOps *dstOps) void OGLContext_SetExtraAlpha(jfloat ea) { - J2dTraceLn1(J2D_TRACE_INFO, "OGLContext_SetExtraAlpha: ea=%f", ea); + J2dTraceLn(J2D_TRACE_INFO, "OGLContext_SetExtraAlpha: ea=%f", ea); j2d_glPixelTransferf(GL_ALPHA_SCALE, ea); j2d_glPixelTransferf(GL_RED_SCALE, ea); @@ -377,8 +377,8 @@ void OGLContext_SetAlphaComposite(OGLContext *oglc, jint rule, jfloat extraAlpha, jint flags) { - J2dTraceLn1(J2D_TRACE_INFO, - "OGLContext_SetAlphaComposite: flags=%d", flags); + J2dTraceLn(J2D_TRACE_INFO, + "OGLContext_SetAlphaComposite: flags=%d", flags); RETURN_IF_NULL(oglc); CHECK_PREVIOUS_OP(OGL_STATE_CHANGE); @@ -398,12 +398,12 @@ OGLContext_SetAlphaComposite(OGLContext *oglc, (extraAlpha == 1.0f) && (flags & OGLC_SRC_IS_OPAQUE)) { - J2dTraceLn1(J2D_TRACE_VERBOSE, - " disabling alpha comp: rule=%d ea=1.0 src=opq", rule); + J2dTraceLn(J2D_TRACE_VERBOSE, + " disabling alpha comp: rule=%d ea=1.0 src=opq", rule); j2d_glDisable(GL_BLEND); } else { - J2dTraceLn2(J2D_TRACE_VERBOSE, - " enabling alpha comp: rule=%d ea=%f", rule, extraAlpha); + J2dTraceLn(J2D_TRACE_VERBOSE, + " enabling alpha comp: rule=%d ea=%f", rule, extraAlpha); j2d_glEnable(GL_BLEND); j2d_glBlendFunc(StdBlendRules[rule].src, StdBlendRules[rule].dst); } @@ -421,8 +421,8 @@ OGLContext_SetAlphaComposite(OGLContext *oglc, void OGLContext_SetXorComposite(OGLContext *oglc, jint xorPixel) { - J2dTraceLn1(J2D_TRACE_INFO, - "OGLContext_SetXorComposite: xorPixel=%08x", xorPixel); + J2dTraceLn(J2D_TRACE_INFO, + "OGLContext_SetXorComposite: xorPixel=%08x", xorPixel); RETURN_IF_NULL(oglc); CHECK_PREVIOUS_OP(OGL_STATE_CHANGE); @@ -497,12 +497,12 @@ OGLContext_SetTransform(OGLContext *oglc, oglc->xformMatrix[12] = m02; oglc->xformMatrix[13] = m12; - J2dTraceLn3(J2D_TRACE_VERBOSE, " [%lf %lf %lf]", - oglc->xformMatrix[0], oglc->xformMatrix[4], - oglc->xformMatrix[12]); - J2dTraceLn3(J2D_TRACE_VERBOSE, " [%lf %lf %lf]", - oglc->xformMatrix[1], oglc->xformMatrix[5], - oglc->xformMatrix[13]); + J2dTraceLn(J2D_TRACE_VERBOSE, " [%lf %lf %lf]", + oglc->xformMatrix[0], oglc->xformMatrix[4], + oglc->xformMatrix[12]); + J2dTraceLn(J2D_TRACE_VERBOSE, " [%lf %lf %lf]", + oglc->xformMatrix[1], oglc->xformMatrix[5], + oglc->xformMatrix[13]); j2d_glMatrixMode(GL_MODELVIEW); j2d_glLoadMatrixd(oglc->xformMatrix); @@ -634,9 +634,9 @@ OGLContext_IsExtensionAvailable(const char *extString, char *extName) p += (n + 1); } - J2dRlsTraceLn2(J2D_TRACE_INFO, - "OGLContext_IsExtensionAvailable: %s=%s", - extName, ret ? "true" : "false"); + J2dRlsTraceLn(J2D_TRACE_INFO, + "OGLContext_IsExtensionAvailable: %s=%s", + extName, ret ? "true" : "false"); return ret; } @@ -751,9 +751,9 @@ OGLContext_IsLCDShaderSupportAvailable(JNIEnv *env, // of texture units j2d_glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS_ARB, &maxTexUnits); if (maxTexUnits < 2) { - J2dRlsTraceLn1(J2D_TRACE_INFO, - "OGLContext_IsLCDShaderSupportAvailable: not enough tex units (%d)", - maxTexUnits); + J2dRlsTraceLn(J2D_TRACE_INFO, + "OGLContext_IsLCDShaderSupportAvailable: not enough tex units (%d)", + maxTexUnits); } J2dRlsTraceLn(J2D_TRACE_INFO, @@ -981,9 +981,9 @@ OGLContext_CreateFragmentProgram(const char *fragmentShaderSource) if (infoLogLength > 1) { char infoLog[1024]; j2d_glGetInfoLogARB(fragmentShader, 1024, NULL, infoLog); - J2dRlsTraceLn2(J2D_TRACE_WARNING, - "OGLContext_CreateFragmentProgram: compiler msg (%d):\n%s", - infoLogLength, infoLog); + J2dRlsTraceLn(J2D_TRACE_WARNING, + "OGLContext_CreateFragmentProgram: compiler msg (%d):\n%s", + infoLogLength, infoLog); } if (!success) { @@ -1013,9 +1013,9 @@ OGLContext_CreateFragmentProgram(const char *fragmentShaderSource) if (infoLogLength > 1) { char infoLog[1024]; j2d_glGetInfoLogARB(fragmentProgram, 1024, NULL, infoLog); - J2dRlsTraceLn2(J2D_TRACE_WARNING, - "OGLContext_CreateFragmentProgram: linker msg (%d):\n%s", - infoLogLength, infoLog); + J2dRlsTraceLn(J2D_TRACE_WARNING, + "OGLContext_CreateFragmentProgram: linker msg (%d):\n%s", + infoLogLength, infoLog); } if (!success) { @@ -1063,7 +1063,7 @@ JNIEXPORT jstring JNICALL Java_sun_java2d_opengl_OGLContext_getOGLIdString jio_snprintf(pAdapterId, len, "%s %s (%s)", vendor, renderer, version); - J2dTraceLn1(J2D_TRACE_VERBOSE, " id=%s", pAdapterId); + J2dTraceLn(J2D_TRACE_VERBOSE, " id=%s", pAdapterId); ret = JNU_NewStringPlatform(env, pAdapterId); diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLFuncs.h b/src/java.desktop/share/native/common/java2d/opengl/OGLFuncs.h index 427c91da2b0..0d24616c2ba 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLFuncs.h +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLFuncs.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -181,7 +181,7 @@ typedef void (GLAPIENTRY *glTextureBarrierNVType) (void); * REMIND: this caused an internal error in the MS compiler!?!? * *#define OGL_CHECK_FUNC_ERR(f) \ - * J2dTrace1(J2D_TRACE_ERROR, "could not load function: %s", #f) + * J2dTrace(J2D_TRACE_ERROR, "could not load function: %s", #f) */ #define OGL_CHECK_FUNC_ERR(f) \ diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLMaskFill.c b/src/java.desktop/share/native/common/java2d/opengl/OGLMaskFill.c index dcb4cff2323..c8310116dcb 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLMaskFill.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLMaskFill.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,9 +94,9 @@ OGLMaskFill_MaskFill(OGLContext *oglc, RETURN_IF_NULL(oglc); CHECK_PREVIOUS_OP(OGL_STATE_MASK_OP); - J2dTraceLn4(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", x, y, w, h); - J2dTraceLn2(J2D_TRACE_VERBOSE, " maskoff=%d maskscan=%d", - maskoff, maskscan); + J2dTraceLn(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, " maskoff=%d maskscan=%d", + maskoff, maskscan); { jint tw, th, x0; diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLPaints.c b/src/java.desktop/share/native/common/java2d/opengl/OGLPaints.c index 89f02cf67fb..4c7b4e04578 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLPaints.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLPaints.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ OGLPaints_ResetPaint(OGLContext *oglc) J2dTraceLn(J2D_TRACE_INFO, "OGLPaints_ResetPaint"); RETURN_IF_NULL(oglc); - J2dTraceLn1(J2D_TRACE_VERBOSE, " state=%d", oglc->paintState); + J2dTraceLn(J2D_TRACE_VERBOSE, " state=%d", oglc->paintState); RESET_PREVIOUS_OP(); if (oglc->useMask) { @@ -102,7 +102,7 @@ OGLPaints_SetColor(OGLContext *oglc, jint pixel) { jubyte r, g, b, a; - J2dTraceLn1(J2D_TRACE_INFO, "OGLPaints_SetColor: pixel=%08x", pixel); + J2dTraceLn(J2D_TRACE_INFO, "OGLPaints_SetColor: pixel=%08x", pixel); RETURN_IF_NULL(oglc); @@ -123,9 +123,9 @@ OGLPaints_SetColor(OGLContext *oglc, jint pixel) b = (jubyte)(pixel >> 0); a = (jubyte)(pixel >> 24); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " updating color: r=%02x g=%02x b=%02x a=%02x", - r, g, b, a); + J2dTraceLn(J2D_TRACE_VERBOSE, + " updating color: r=%02x g=%02x b=%02x a=%02x", + r, g, b, a); } else { pixel ^= oglc->xorPixel; @@ -134,9 +134,9 @@ OGLPaints_SetColor(OGLContext *oglc, jint pixel) b = (jubyte)(pixel >> 0); a = 0xff; - J2dTraceLn4(J2D_TRACE_VERBOSE, - " updating xor color: r=%02x g=%02x b=%02x xorpixel=%08x", - r, g, b, oglc->xorPixel); + J2dTraceLn(J2D_TRACE_VERBOSE, + " updating xor color: r=%02x g=%02x b=%02x xorpixel=%08x", + r, g, b, oglc->xorPixel); } j2d_glColor4ub(r, g, b, a); @@ -704,9 +704,9 @@ OGLPaints_CreateLinearGradProgram(jint flags) char *paintVars; char *distCode; - J2dTraceLn1(J2D_TRACE_INFO, - "OGLPaints_CreateLinearGradProgram", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "OGLPaints_CreateLinearGradProgram", + flags); /* * To simplify the code and to make it easier to upload a number of @@ -808,9 +808,9 @@ OGLPaints_CreateRadialGradProgram(jint flags) char *paintVars; char *distCode; - J2dTraceLn1(J2D_TRACE_INFO, - "OGLPaints_CreateRadialGradProgram", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "OGLPaints_CreateRadialGradProgram", + flags); /* * To simplify the code and to make it easier to upload a number of diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLRenderQueue.c b/src/java.desktop/share/native/common/java2d/opengl/OGLRenderQueue.c index 6328707a3e2..2bafc33f588 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLRenderQueue.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLRenderQueue.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,8 +73,8 @@ Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer jboolean sync = JNI_FALSE; unsigned char *b, *end; - J2dTraceLn1(J2D_TRACE_INFO, - "OGLRenderQueue_flushBuffer: limit=%d", limit); + J2dTraceLn(J2D_TRACE_INFO, + "OGLRenderQueue_flushBuffer: limit=%d", limit); b = (unsigned char *)jlong_to_ptr(buf); if (b == NULL) { @@ -89,9 +89,9 @@ Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer while (b < end) { jint opcode = NEXT_INT(b); - J2dTraceLn2(J2D_TRACE_VERBOSE, - "OGLRenderQueue_flushBuffer: opcode=%d, rem=%d", - opcode, (end-b)); + J2dTraceLn(J2D_TRACE_VERBOSE, + "OGLRenderQueue_flushBuffer: opcode=%d, rem=%d", + opcode, (end-b)); switch (opcode) { @@ -667,8 +667,9 @@ Java_sun_java2d_opengl_OGLRenderQueue_flushBuffer break; default: - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "OGLRenderQueue_flushBuffer: invalid opcode=%d", opcode); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "OGLRenderQueue_flushBuffer: invalid opcode=%d", + opcode); if (oglc != NULL) { RESET_PREVIOUS_OP(); } @@ -756,8 +757,8 @@ OGLRenderQueue_CheckPreviousOp(jint op) return; } - J2dTraceLn1(J2D_TRACE_VERBOSE, - "OGLRenderQueue_CheckPreviousOp: new op=%d", op); + J2dTraceLn(J2D_TRACE_VERBOSE, + "OGLRenderQueue_CheckPreviousOp: new op=%d", op); switch (previousOp) { case GL_TEXTURE_2D: diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLRenderQueue.h b/src/java.desktop/share/native/common/java2d/opengl/OGLRenderQueue.h index 88bd4e5448d..2f2692313dc 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLRenderQueue.h +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLRenderQueue.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,8 +114,8 @@ */ #define ACT_IF_NULL(ACTION, value) \ if ((value) == NULL) { \ - J2dTraceLn1(J2D_TRACE_ERROR, \ - "%s is null", #value); \ + J2dTraceLn(J2D_TRACE_ERROR, \ + "%s is null", #value); \ ACTION; \ } else do { } while (0) #define RETURN_IF_NULL(value) ACT_IF_NULL(return, value) diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLRenderer.c b/src/java.desktop/share/native/common/java2d/opengl/OGLRenderer.c index fa303643ed7..88f18b6cda2 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLRenderer.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLRenderer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -341,14 +341,14 @@ OGLRenderer_FillParallelogram(OGLContext *oglc, jfloat dx21, jfloat dy21, jfloat dx12, jfloat dy12) { - J2dTraceLn6(J2D_TRACE_INFO, - "OGLRenderer_FillParallelogram " - "(x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f " - "dx2=%6.2f dy2=%6.2f)", - fx11, fy11, - dx21, dy21, - dx12, dy12); + J2dTraceLn(J2D_TRACE_INFO, + "OGLRenderer_FillParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f " + "dx2=%6.2f dy2=%6.2f)", + fx11, fy11, + dx21, dy21, + dx12, dy12); RETURN_IF_NULL(oglc); @@ -374,14 +374,14 @@ OGLRenderer_DrawParallelogram(OGLContext *oglc, jfloat ox11 = fx11 - (ldx21 + ldx12) / 2.0f; jfloat oy11 = fy11 - (ldy21 + ldy12) / 2.0f; - J2dTraceLn8(J2D_TRACE_INFO, - "OGLRenderer_DrawParallelogram " - "(x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " - "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", - fx11, fy11, - dx21, dy21, lwr21, - dx12, dy12, lwr12); + J2dTraceLn(J2D_TRACE_INFO, + "OGLRenderer_DrawParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " + "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", + fx11, fy11, + dx21, dy21, lwr21, + dx12, dy12, lwr12); RETURN_IF_NULL(oglc); @@ -596,14 +596,14 @@ OGLRenderer_FillAAParallelogram(OGLContext *oglc, OGLSDOps *dstOps, // parameters for uv texture coordinates of parallelogram corners jfloat u11, v11, u12, v12, u21, v21, u22, v22; - J2dTraceLn6(J2D_TRACE_INFO, - "OGLRenderer_FillAAParallelogram " - "(x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f " - "dx2=%6.2f dy2=%6.2f)", - fx11, fy11, - dx21, dy21, - dx12, dy12); + J2dTraceLn(J2D_TRACE_INFO, + "OGLRenderer_FillAAParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f " + "dx2=%6.2f dy2=%6.2f)", + fx11, fy11, + dx21, dy21, + dx12, dy12); RETURN_IF_NULL(oglc); RETURN_IF_NULL(dstOps); @@ -731,14 +731,14 @@ OGLRenderer_DrawAAParallelogram(OGLContext *oglc, OGLSDOps *dstOps, // parameters for "inner" parallelogram jfloat ifx11, ify11, idx21, idy21, idx12, idy12; - J2dTraceLn8(J2D_TRACE_INFO, - "OGLRenderer_DrawAAParallelogram " - "(x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " - "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", - fx11, fy11, - dx21, dy21, lwr21, - dx12, dy12, lwr12); + J2dTraceLn(J2D_TRACE_INFO, + "OGLRenderer_DrawAAParallelogram " + "(x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " + "dx2=%6.2f dy2=%6.2f lwr2=%6.2f)", + fx11, fy11, + dx21, dy21, lwr21, + dx12, dy12, lwr12); RETURN_IF_NULL(oglc); RETURN_IF_NULL(dstOps); diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c b/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c index f7b0f85fe06..8639c4193cf 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -142,9 +142,9 @@ OGLSD_InitTextureObject(OGLSDOps *oglsdo, GLsizei texWidth, texHeight, realWidth, realHeight; GLint texMax; - J2dTraceLn4(J2D_TRACE_INFO, - "OGLSD_InitTextureObject: w=%d h=%d opq=%d nonpow2=%d", - width, height, isOpaque, texNonPow2); + J2dTraceLn(J2D_TRACE_INFO, + "OGLSD_InitTextureObject: w=%d h=%d opq=%d nonpow2=%d", + width, height, isOpaque, texNonPow2); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, @@ -175,9 +175,9 @@ OGLSD_InitTextureObject(OGLSDOps *oglsdo, texProxyTarget = GL_PROXY_TEXTURE_2D; } - J2dTraceLn3(J2D_TRACE_VERBOSE, - " desired texture dimensions: w=%d h=%d max=%d", - texWidth, texHeight, texMax); + J2dTraceLn(J2D_TRACE_VERBOSE, + " desired texture dimensions: w=%d h=%d max=%d", + texWidth, texHeight, texMax); // if either dimension is 0, we cannot allocate a texture with the // requested dimensions @@ -200,9 +200,8 @@ OGLSD_InitTextureObject(OGLSDOps *oglsdo, // if the requested dimensions and proxy dimensions don't match, // we shouldn't attempt to create the texture if ((realWidth != texWidth) || (realHeight != texHeight)) { - J2dRlsTraceLn2(J2D_TRACE_ERROR, - "OGLSD_InitTextureObject: actual (w=%d h=%d) != requested", - realWidth, realHeight); + J2dRlsTraceLn(J2D_TRACE_ERROR, "OGLSD_InitTextureObject: "\ + "actual (w=%d h=%d) != requested", realWidth, realHeight); return JNI_FALSE; } @@ -227,8 +226,8 @@ OGLSD_InitTextureObject(OGLSDOps *oglsdo, OGLSD_INIT_TEXTURE_FILTER(oglsdo, GL_NEAREST); OGLSD_RESET_TEXTURE_WRAP(texTarget); - J2dTraceLn3(J2D_TRACE_VERBOSE, " created texture: w=%d h=%d id=%d", - width, height, texID); + J2dTraceLn(J2D_TRACE_VERBOSE, " created texture: w=%d h=%d id=%d", + width, height, texID); return JNI_TRUE; } @@ -246,8 +245,8 @@ Java_sun_java2d_opengl_OGLSurfaceData_initTexture { OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); - J2dTraceLn2(J2D_TRACE_INFO, "OGLSurfaceData_initTexture: w=%d h=%d", - width, height); + J2dTraceLn(J2D_TRACE_INFO, "OGLSurfaceData_initTexture: w=%d h=%d", + width, height); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, @@ -306,8 +305,8 @@ OGLSD_InitFBObject(GLuint *fbobjectID, GLuint *depthID, jboolean foundDepth = JNI_FALSE; int i; - J2dTraceLn3(J2D_TRACE_INFO, "OGLSD_InitFBObject: w=%d h=%d texid=%d", - textureWidth, textureHeight, textureID); + J2dTraceLn(J2D_TRACE_INFO, "OGLSD_InitFBObject: w=%d h=%d texid=%d", + textureWidth, textureHeight, textureID); // initialize framebuffer object j2d_glGenFramebuffersEXT(1, &fboTmpID); @@ -334,9 +333,9 @@ OGLSD_InitFBObject(GLuint *fbobjectID, GLuint *depthID, // creation of depth buffer could potentially fail, so check for error error = j2d_glGetError(); if (error != GL_NO_ERROR) { - J2dTraceLn2(J2D_TRACE_VERBOSE, - "OGLSD_InitFBObject: could not create depth buffer: depth=%d error=%x", - depthSize, error); + J2dTraceLn(J2D_TRACE_VERBOSE, "OGLSD_InitFBObject: "\ + "could not create depth buffer: depth=%d error=%x", + depthSize, error); j2d_glDeleteRenderbuffersEXT(1, &depthTmpID); continue; } @@ -351,15 +350,15 @@ OGLSD_InitFBObject(GLuint *fbobjectID, GLuint *depthID, if (status == GL_FRAMEBUFFER_COMPLETE_EXT) { // we found a valid format, so break out of the loop - J2dTraceLn1(J2D_TRACE_VERBOSE, - " framebuffer is complete: depth=%d", depthSize); + J2dTraceLn(J2D_TRACE_VERBOSE, + " framebuffer is complete: depth=%d", depthSize); foundDepth = JNI_TRUE; break; } else { // this depth format didn't work, so delete and try another format - J2dTraceLn2(J2D_TRACE_VERBOSE, - " framebuffer is incomplete: depth=%d status=%x", - depthSize, status); + J2dTraceLn(J2D_TRACE_VERBOSE, + " framebuffer is incomplete: depth=%d status=%x", + depthSize, status); j2d_glDeleteRenderbuffersEXT(1, &depthTmpID); } } @@ -398,9 +397,9 @@ Java_sun_java2d_opengl_OGLSurfaceData_initFBObject OGLSDOps *oglsdo = (OGLSDOps *)jlong_to_ptr(pData); GLuint fbobjectID, depthID; - J2dTraceLn2(J2D_TRACE_INFO, - "OGLSurfaceData_initFBObject: w=%d h=%d", - width, height); + J2dTraceLn(J2D_TRACE_INFO, + "OGLSurfaceData_initFBObject: w=%d h=%d", + width, height); if (oglsdo == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, @@ -555,8 +554,8 @@ OGLSD_SetNativeDimensions(JNIEnv *env, OGLSDOps *oglsdo, void OGLSD_Delete(JNIEnv *env, OGLSDOps *oglsdo) { - J2dTraceLn1(J2D_TRACE_INFO, "OGLSD_Delete: type=%d", - oglsdo->drawableType); + J2dTraceLn(J2D_TRACE_INFO, "OGLSD_Delete: type=%d", + oglsdo->drawableType); if (oglsdo->drawableType == OGLSD_TEXTURE) { if (oglsdo->textureID != 0) { diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLTextRenderer.c b/src/java.desktop/share/native/common/java2d/opengl/OGLTextRenderer.c index 19389066f87..118015bf8f6 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLTextRenderer.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLTextRenderer.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -347,8 +347,8 @@ OGLTR_UpdateLCDTextContrast(jint contrast) double ig = 1.0 / g; GLint loc; - J2dTraceLn1(J2D_TRACE_INFO, - "OGLTR_UpdateLCDTextContrast: contrast=%d", contrast); + J2dTraceLn(J2D_TRACE_INFO, + "OGLTR_UpdateLCDTextContrast: contrast=%d", contrast); loc = j2d_glGetUniformLocationARB(lcdTextProgram, "gamma"); j2d_glUniform3fARB(loc, g, g, g); @@ -376,8 +376,8 @@ OGLTR_UpdateLCDTextColor(jint contrast) GLfloat clr[4]; GLint loc; - J2dTraceLn1(J2D_TRACE_INFO, - "OGLTR_UpdateLCDTextColor: contrast=%d", contrast); + J2dTraceLn(J2D_TRACE_INFO, + "OGLTR_UpdateLCDTextColor: contrast=%d", contrast); /* * Note: Ideally we would update the "src_adj" uniform parameter only diff --git a/src/java.desktop/share/native/common/java2d/opengl/OGLVertexCache.c b/src/java.desktop/share/native/common/java2d/opengl/OGLVertexCache.c index 21d67705ec5..c63aad9f2d9 100644 --- a/src/java.desktop/share/native/common/java2d/opengl/OGLVertexCache.c +++ b/src/java.desktop/share/native/common/java2d/opengl/OGLVertexCache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -220,8 +220,8 @@ OGLVertexCache_AddMaskQuad(OGLContext *oglc, jfloat tx1, ty1, tx2, ty2; jfloat dx1, dy1, dx2, dy2; - J2dTraceLn1(J2D_TRACE_INFO, "OGLVertexCache_AddMaskQuad: %d", - maskCacheIndex); + J2dTraceLn(J2D_TRACE_INFO, "OGLVertexCache_AddMaskQuad: %d", + maskCacheIndex); if (maskCacheIndex >= OGLVC_MASK_CACHE_MAX_INDEX || vertexCacheIndex >= OGLVC_MAX_INDEX) diff --git a/src/java.desktop/share/native/libawt/java2d/Trace.h b/src/java.desktop/share/native/libawt/java2d/Trace.h index b4fe41f77b0..365042a3971 100644 --- a/src/java.desktop/share/native/libawt/java2d/Trace.h +++ b/src/java.desktop/share/native/libawt/java2d/Trace.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,79 +54,13 @@ JNIEXPORT void JNICALL J2dTraceImpl(int level, jboolean cr, const char *string, ...); #ifndef DEBUG -#define J2dTrace(level, string) -#define J2dTrace1(level, string, arg1) -#define J2dTrace2(level, string, arg1, arg2) -#define J2dTrace3(level, string, arg1, arg2, arg3) -#define J2dTrace4(level, string, arg1, arg2, arg3, arg4) -#define J2dTrace5(level, string, arg1, arg2, arg3, arg4, arg5) -#define J2dTrace6(level, string, arg1, arg2, arg3, arg4, arg5, arg6) -#define J2dTrace7(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) -#define J2dTrace8(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) -#define J2dTraceLn(level, string) -#define J2dTraceLn1(level, string, arg1) -#define J2dTraceLn2(level, string, arg1, arg2) -#define J2dTraceLn3(level, string, arg1, arg2, arg3) -#define J2dTraceLn4(level, string, arg1, arg2, arg3, arg4) -#define J2dTraceLn5(level, string, arg1, arg2, arg3, arg4, arg5) -#define J2dTraceLn6(level, string, arg1, arg2, arg3, arg4, arg5, arg6) -#define J2dTraceLn7(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) -#define J2dTraceLn8(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) +#define J2dTrace(level, ...) +#define J2dTraceLn(level, ...) #else /* DEBUG */ -#define J2dTrace(level, string) { \ - J2dTraceImpl(level, JNI_FALSE, string); \ - } -#define J2dTrace1(level, string, arg1) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1); \ - } -#define J2dTrace2(level, string, arg1, arg2) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2); \ - } -#define J2dTrace3(level, string, arg1, arg2, arg3) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3); \ - } -#define J2dTrace4(level, string, arg1, arg2, arg3, arg4) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4); \ - } -#define J2dTrace5(level, string, arg1, arg2, arg3, arg4, arg5) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4, arg5); \ - } -#define J2dTrace6(level, string, arg1, arg2, arg3, arg4, arg5, arg6) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4, arg5, arg6); \ - } -#define J2dTrace7(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ - } -#define J2dTrace8(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ - } -#define J2dTraceLn(level, string) { \ - J2dTraceImpl(level, JNI_TRUE, string); \ - } -#define J2dTraceLn1(level, string, arg1) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1); \ - } -#define J2dTraceLn2(level, string, arg1, arg2) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2); \ - } -#define J2dTraceLn3(level, string, arg1, arg2, arg3) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3); \ - } -#define J2dTraceLn4(level, string, arg1, arg2, arg3, arg4) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4); \ - } -#define J2dTraceLn5(level, string, arg1, arg2, arg3, arg4, arg5) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4, arg5); \ - } -#define J2dTraceLn6(level, string, arg1, arg2, arg3, arg4, arg5, arg6) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4, arg5, arg6); \ - } -#define J2dTraceLn7(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7); \ - } -#define J2dTraceLn8(level, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); \ - } +#define J2dTrace(level, ...) \ + J2dTraceImpl(level, JNI_FALSE, __VA_ARGS__) +#define J2dTraceLn(level, ...) \ + J2dTraceImpl(level, JNI_TRUE, __VA_ARGS__) #endif /* DEBUG */ @@ -136,42 +70,10 @@ J2dTraceImpl(int level, jboolean cr, const char *string, ...); * areas. */ -#define J2dRlsTrace(level, string) { \ - J2dTraceImpl(level, JNI_FALSE, string); \ - } -#define J2dRlsTrace1(level, string, arg1) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1); \ - } -#define J2dRlsTrace2(level, string, arg1, arg2) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2); \ - } -#define J2dRlsTrace3(level, string, arg1, arg2, arg3) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3); \ - } -#define J2dRlsTrace4(level, string, arg1, arg2, arg3, arg4) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4); \ - } -#define J2dRlsTrace5(level, string, arg1, arg2, arg3, arg4, arg5) { \ - J2dTraceImpl(level, JNI_FALSE, string, arg1, arg2, arg3, arg4, arg5); \ - } -#define J2dRlsTraceLn(level, string) { \ - J2dTraceImpl(level, JNI_TRUE, string); \ - } -#define J2dRlsTraceLn1(level, string, arg1) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1); \ - } -#define J2dRlsTraceLn2(level, string, arg1, arg2) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2); \ - } -#define J2dRlsTraceLn3(level, string, arg1, arg2, arg3) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3); \ - } -#define J2dRlsTraceLn4(level, string, arg1, arg2, arg3, arg4) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4); \ - } -#define J2dRlsTraceLn5(level, string, arg1, arg2, arg3, arg4, arg5) { \ - J2dTraceImpl(level, JNI_TRUE, string, arg1, arg2, arg3, arg4, arg5); \ - } +#define J2dRlsTrace(level, ...) \ + J2dTraceImpl(level, JNI_FALSE, __VA_ARGS__) +#define J2dRlsTraceLn(level, ...) \ + J2dTraceImpl(level, JNI_TRUE, __VA_ARGS__) #ifdef __cplusplus } diff --git a/src/java.desktop/share/native/libawt/java2d/loops/DrawParallelogram.c b/src/java.desktop/share/native/libawt/java2d/loops/DrawParallelogram.c index 6bff9ef8081..6f4caaaa7f2 100644 --- a/src/java.desktop/share/native/libawt/java2d/loops/DrawParallelogram.c +++ b/src/java.desktop/share/native/libawt/java2d/loops/DrawParallelogram.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -274,10 +274,10 @@ Java_sun_java2d_loops_DrawParallelogram_DrawParallelogram } #ifdef DEBUG if ((numactive & 1) != 0) { - J2dTraceLn1(J2D_TRACE_ERROR, - "DrawParallelogram: " - "ODD NUMBER OF PGRAM EDGES (%d)!!", - numactive); + J2dTraceLn(J2D_TRACE_ERROR, + "DrawParallelogram: " + "ODD NUMBER OF PGRAM EDGES (%d)!!", + numactive); } #endif for (cur = 0; cur < numactive; cur += 2) { diff --git a/src/java.desktop/share/native/libawt/java2d/pipe/BufferedMaskBlit.c b/src/java.desktop/share/native/libawt/java2d/pipe/BufferedMaskBlit.c index b5ba039a237..77b7ec091c0 100644 --- a/src/java.desktop/share/native/libawt/java2d/pipe/BufferedMaskBlit.c +++ b/src/java.desktop/share/native/libawt/java2d/pipe/BufferedMaskBlit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,9 +62,9 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile unsigned char *bbuf; jint *pBuf; - J2dTraceLn1(J2D_TRACE_INFO, - "BufferedMaskBlit_enqueueTile: bpos=%d", - bpos); + J2dTraceLn(J2D_TRACE_INFO, + "BufferedMaskBlit_enqueueTile: bpos=%d", + bpos); if (srcOps == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, @@ -139,15 +139,15 @@ Java_sun_java2d_pipe_BufferedMaskBlit_enqueueTile srcScanStride -= width * srcPixelStride; h = height; - J2dTraceLn4(J2D_TRACE_VERBOSE, - " sx=%d sy=%d w=%d h=%d", - srcInfo.bounds.x1, srcInfo.bounds.y1, width, height); - J2dTraceLn2(J2D_TRACE_VERBOSE, - " maskoff=%d maskscan=%d", - maskoff, maskscan); - J2dTraceLn2(J2D_TRACE_VERBOSE, - " pixstride=%d scanstride=%d", - srcPixelStride, srcScanStride); + J2dTraceLn(J2D_TRACE_VERBOSE, + " sx=%d sy=%d w=%d h=%d", + srcInfo.bounds.x1, srcInfo.bounds.y1, width, height); + J2dTraceLn(J2D_TRACE_VERBOSE, + " maskoff=%d maskscan=%d", + maskoff, maskscan); + J2dTraceLn(J2D_TRACE_VERBOSE, + " pixstride=%d scanstride=%d", + srcPixelStride, srcScanStride); // enqueue parameters pBuf[0] = sun_java2d_pipe_BufferedOpCodes_MASK_BLIT; diff --git a/src/java.desktop/share/native/libawt/java2d/pipe/BufferedRenderPipe.c b/src/java.desktop/share/native/libawt/java2d/pipe/BufferedRenderPipe.c index ac55c38f932..a36b2128259 100644 --- a/src/java.desktop/share/native/libawt/java2d/pipe/BufferedRenderPipe.c +++ b/src/java.desktop/share/native/libawt/java2d/pipe/BufferedRenderPipe.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,9 +59,9 @@ Java_sun_java2d_pipe_BufferedRenderPipe_fillSpans jint ipos; jboolean hasException; - J2dTraceLn2(J2D_TRACE_INFO, - "BufferedRenderPipe_fillSpans: bpos=%d limit=%d", - bpos, limit); + J2dTraceLn(J2D_TRACE_INFO, + "BufferedRenderPipe_fillSpans: bpos=%d limit=%d", + bpos, limit); if (JNU_IsNull(env, rq)) { J2dRlsTraceLn(J2D_TRACE_ERROR, diff --git a/src/java.desktop/unix/native/common/java2d/opengl/GLXGraphicsConfig.c b/src/java.desktop/unix/native/common/java2d/opengl/GLXGraphicsConfig.c index b5232b7a912..47c5a6d0d2e 100644 --- a/src/java.desktop/unix/native/common/java2d/opengl/GLXGraphicsConfig.c +++ b/src/java.desktop/unix/native/common/java2d/opengl/GLXGraphicsConfig.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,8 +96,8 @@ GLXGC_InitGLX() // we now only verify that the client GLX version is >= 1.3 (if the // server does not support GLX 1.3, then we will find that out later // when we attempt to create a GLXFBConfig) - J2dRlsTraceLn1(J2D_TRACE_INFO, - "GLXGC_InitGLX: client GLX version=%s", version); + J2dRlsTraceLn(J2D_TRACE_INFO, + "GLXGC_InitGLX: client GLX version=%s", version); if (!((version[0] == '1' && version[2] >= '3') || (version[0] > '1'))) { J2dRlsTraceLn(J2D_TRACE_ERROR, "GLXGC_InitGLX: invalid GLX version; 1.3 is required"); @@ -224,8 +224,8 @@ GLXGC_InitFBConfig(JNIEnv *env, jint screennum, VisualID visualid) // be much less than this number) int minDepthPlusStencil = 512; - J2dRlsTraceLn2(J2D_TRACE_INFO, "GLXGC_InitFBConfig: scn=%d vis=0x%x", - screennum, visualid); + J2dRlsTraceLn(J2D_TRACE_INFO, "GLXGC_InitFBConfig: scn=%d vis=0x%x", + screennum, visualid); // find all fbconfigs for this screen with the provided attributes fbconfigs = j2d_glXChooseFBConfig(awt_display, screennum, @@ -275,9 +275,9 @@ GLXGC_InitFBConfig(JNIEnv *env, jint screennum, VisualID visualid) j2d_glXGetFBConfigAttrib(awt_display, fbc, GLX_ALPHA_SIZE, &alpha); - J2dRlsTrace5(J2D_TRACE_VERBOSE, - "[V] id=0x%x db=%d alpha=%d depth=%d stencil=%d valid=", - fbvisualid, db, alpha, depth, stencil); + J2dRlsTrace(J2D_TRACE_VERBOSE, + "[V] id=0x%x db=%d alpha=%d depth=%d stencil=%d valid=", + fbvisualid, db, alpha, depth, stencil); if ((dtype & GLX_WINDOW_BIT) && (dtype & GLX_PBUFFER_BIT) && @@ -337,7 +337,7 @@ GLXGC_FindBestVisual(JNIEnv *env, jint screen) XVisualInfo *xvi; VisualID visualid; - J2dRlsTraceLn1(J2D_TRACE_INFO, "GLXGC_FindBestVisual: scn=%d", screen); + J2dRlsTraceLn(J2D_TRACE_INFO, "GLXGC_FindBestVisual: scn=%d", screen); if (!GLXGC_IsGLXAvailable()) { J2dRlsTraceLn(J2D_TRACE_ERROR, @@ -362,9 +362,9 @@ GLXGC_FindBestVisual(JNIEnv *env, jint screen) visualid = xvi->visualid; XFree(xvi); - J2dRlsTraceLn2(J2D_TRACE_INFO, - "GLXGC_FindBestVisual: chose 0x%x as the best visual for screen %d", - visualid, screen); + J2dRlsTraceLn(J2D_TRACE_INFO, + "GLXGC_FindBestVisual: chose 0x%x as the best visual for screen %d", + visualid, screen); return visualid; } @@ -510,9 +510,9 @@ Java_sun_java2d_opengl_GLXGraphicsConfig_getGLXConfigInfo(JNIEnv *env, // destroy the temporary resources j2d_glXMakeContextCurrent(awt_display, None, None, NULL); - J2dRlsTraceLn1(J2D_TRACE_INFO, - "GLXGraphicsConfig_getGLXConfigInfo: OpenGL version=%s", - (versionstr == NULL) ? "null" : (char *)versionstr); + J2dRlsTraceLn(J2D_TRACE_INFO, + "GLXGraphicsConfig_getGLXConfigInfo: OpenGL version=%s", + (versionstr == NULL) ? "null" : (char *)versionstr); if (!OGLContext_IsVersionSupported(versionstr)) { J2dRlsTraceLn(J2D_TRACE_ERROR, diff --git a/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c b/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c index c48b38fa1f3..8f264278d9f 100644 --- a/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c +++ b/src/java.desktop/unix/native/common/java2d/opengl/GLXSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -307,8 +307,8 @@ OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo) glxsdo->drawable = window; glxsdo->xdrawable = window; - J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", - oglsdo->width, oglsdo->height); + J2dTraceLn(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", + oglsdo->width, oglsdo->height); return JNI_TRUE; } diff --git a/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c b/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c index 2349ad3dcfd..b134623a0bd 100644 --- a/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c +++ b/src/java.desktop/unix/native/common/java2d/x11/X11SurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -534,9 +534,9 @@ XImage* X11SD_CreateSharedImage(X11SDOps *xsdo, shmget(IPC_PRIVATE, (size_t) height * img->bytes_per_line, IPC_CREAT|mitShmPermissionMask); if (shminfo->shmid < 0) { - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "X11SD_SetupSharedSegment shmget has failed: %s", - strerror(errno)); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "X11SD_SetupSharedSegment shmget has failed: %s", + strerror(errno)); free((void *)shminfo); XDestroyImage(img); return NULL; @@ -545,9 +545,9 @@ XImage* X11SD_CreateSharedImage(X11SDOps *xsdo, shminfo->shmaddr = (char *) shmat(shminfo->shmid, 0, 0); if (shminfo->shmaddr == ((char *) -1)) { shmctl(shminfo->shmid, IPC_RMID, 0); - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "X11SD_SetupSharedSegment shmat has failed: %s", - strerror(errno)); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "X11SD_SetupSharedSegment shmat has failed: %s", + strerror(errno)); free((void *)shminfo); XDestroyImage(img); return NULL; @@ -567,9 +567,9 @@ XImage* X11SD_CreateSharedImage(X11SDOps *xsdo, shmctl(shminfo->shmid, IPC_RMID, 0); if (isXShmAttachFailed() == JNI_TRUE) { - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "X11SD_SetupSharedSegment XShmAttach has failed: %s", - strerror(errno)); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "X11SD_SetupSharedSegment XShmAttach has failed: %s", + strerror(errno)); shmdt(shminfo->shmaddr); free((void *)shminfo); XDestroyImage(img); diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c index fdb2bbb3ab9..c7fe9c879ff 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/awt_GraphicsEnv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -897,18 +897,18 @@ void TryInitMITShm(JNIEnv *env, jint *shmExt, jint *shmPixmaps) { IPC_CREAT|mitShmPermissionMask); if (shminfo.shmid < 0) { AWT_UNLOCK(); - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "TryInitMITShm: shmget has failed: %s", - strerror(errno)); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "TryInitMITShm: shmget has failed: %s", + strerror(errno)); return; } shminfo.shmaddr = (char *) shmat(shminfo.shmid, 0, 0); if (shminfo.shmaddr == ((char *) -1)) { shmctl(shminfo.shmid, IPC_RMID, 0); AWT_UNLOCK(); - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "TryInitMITShm: shmat has failed: %s", - strerror(errno)); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "TryInitMITShm: shmat has failed: %s", + strerror(errno)); return; } shminfo.readOnly = True; @@ -1525,8 +1525,8 @@ static XRRFreeCrtcInfoType awt_XRRFreeCrtcInfo; do { \ awt_##f = (f##Type)dlsym(pLibRandR, #f); \ if (awt_##f == NULL) { \ - J2dRlsTraceLn1(J2D_TRACE_ERROR, \ - "X11GD_InitXrandrFuncs: Could not load %s", #f); \ + J2dRlsTraceLn(J2D_TRACE_ERROR, \ + "X11GD_InitXrandrFuncs: Could not load %s", #f); \ dlclose(pLibRandR); \ return JNI_FALSE; \ } \ @@ -1564,9 +1564,9 @@ X11GD_InitXrandrFuncs(JNIEnv *env) * a fake one provided by RANDR itself. See Java bug 6636469 for info. */ if (!(rr_maj_ver > 1 || (rr_maj_ver == 1 && rr_min_ver >= 2))) { - J2dRlsTraceLn2(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. " - "Xinerama is active and Xrandr version is %d.%d", - rr_maj_ver, rr_min_ver); + J2dRlsTraceLn(J2D_TRACE_INFO, "X11GD_InitXrandrFuncs: Can't use Xrandr. " + "Xinerama is active and Xrandr version is %d.%d", + rr_maj_ver, rr_min_ver); dlclose(pLibRandR); return JNI_FALSE; } diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBlitLoops.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBlitLoops.cpp index ecf8100e87d..b1c946edcf6 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBlitLoops.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBlitLoops.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -69,9 +69,9 @@ D3DBL_CopySurfaceToIntArgbImage(IDirect3DSurface9 *pSurface, SurfaceDataRasInfo srcInfo; J2dTraceLn(J2D_TRACE_INFO, "D3DBL_CopySurfaceToIntArgbImage"); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " rect={%-4d, %-4d, %-4d, %-4d}", - r.left, r.top, r.right, r.bottom); + J2dTraceLn(J2D_TRACE_VERBOSE, + " rect={%-4d, %-4d, %-4d, %-4d}", + r.left, r.top, r.right, r.bottom); res = pSurface->LockRect(&lockedRect, &r, D3DLOCK_NOSYSLOCK); RETURN_STATUS_IF_FAILED(res); @@ -121,9 +121,9 @@ D3DBL_CopySurfaceToIntArgbImage(IDirect3DSurface9 *pSurface, &srcInfo, pDstInfo, NULL, NULL); break; default: - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DBL_CopySurfaceToIntArgbImage: unknown format %d", - desc.Format); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DBL_CopySurfaceToIntArgbImage: unknown format %d", + desc.Format); } return pSurface->UnlockRect(); @@ -147,9 +147,9 @@ D3DBL_CopyImageToIntXrgbSurface(SurfaceDataRasInfo *pSrcInfo, DWORD dwLockFlags = D3DLOCK_NOSYSLOCK; J2dTraceLn(J2D_TRACE_INFO, "D3DBL_CopyImageToIntXrgbSurface"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " srctype=%d rect={%-4d, %-4d, %-4d, %-4d}", - srctype, r.left, r.top, r.right, r.bottom); + J2dTraceLn(J2D_TRACE_VERBOSE, + " srctype=%d rect={%-4d, %-4d, %-4d, %-4d}", + srctype, r.left, r.top, r.right, r.bottom); if (pDesc->Usage == D3DUSAGE_DYNAMIC) { // it is safe to lock with discard because we don't care about the @@ -238,9 +238,9 @@ D3DBL_CopyImageToIntXrgbSurface(SurfaceDataRasInfo *pSrcInfo, // pSrcInfo, &dstInfo, NULL, NULL); break; default: - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DBL_CopyImageToIntXrgbSurface: unknown type %d", - srctype); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DBL_CopyImageToIntXrgbSurface: unknown type %d", + srctype); } return pDstSurface->UnlockRect(); @@ -676,11 +676,11 @@ D3DBlitLoops_IsoBlit(JNIEnv *env, sy2 = srcInfo.bounds.y2; } - J2dTraceLn2(J2D_TRACE_VERBOSE, " texture=%d hint=%d", texture, hint); - J2dTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", - sx1, sy1, sx2, sy2); - J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", - dx1, dy1, dx2, dy2); + J2dTraceLn(J2D_TRACE_VERBOSE, " texture=%d hint=%d", texture, hint); + J2dTraceLn(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", + sx1, sy1, sx2, sy2); + J2dTraceLn(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", + dx1, dy1, dx2, dy2); D3DTEXTUREFILTERTYPE fhint = (hint == D3DSD_XFORM_BILINEAR) ? D3DTEXF_LINEAR : D3DTEXF_POINT; @@ -697,8 +697,8 @@ D3DBlitLoops_IsoBlit(JNIEnv *env, DWORD abEnabled = 0; pd3dDevice->GetRenderState(D3DRS_ALPHABLENDENABLE, &abEnabled); - J2dTraceLn3(J2D_TRACE_VERBOSE, " xform=%d clip=%d abEnabled=%d", - xform, d3dc->GetClipType(), abEnabled); + J2dTraceLn(J2D_TRACE_VERBOSE, " xform=%d clip=%d abEnabled=%d", + xform, d3dc->GetClipType(), abEnabled); if (!xform && d3dc->GetClipType() != CLIP_SHAPE && !abEnabled) { fhint = d3dc->IsStretchRectFilteringSupported(fhint) ? fhint : D3DTEXF_NONE; @@ -794,12 +794,12 @@ D3DBlitLoops_Blit(JNIEnv *env, sy2 = srcInfo.bounds.y2; } - J2dTraceLn3(J2D_TRACE_VERBOSE, " texture=%d srctype=%d hint=%d", - texture, srctype, hint); - J2dTraceLn4(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", - sx1, sy1, sx2, sy2); - J2dTraceLn4(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", - dx1, dy1, dx2, dy2); + J2dTraceLn(J2D_TRACE_VERBOSE, " texture=%d srctype=%d hint=%d", + texture, srctype, hint); + J2dTraceLn(J2D_TRACE_VERBOSE, " sx1=%d sy1=%d sx2=%d sy2=%d", + sx1, sy1, sx2, sy2); + J2dTraceLn(J2D_TRACE_VERBOSE, " dx1=%f dy1=%f dx2=%f dy2=%f", + dx1, dy1, dx2, dy2); if (texture) { // These coordinates will always be integers since we @@ -889,10 +889,10 @@ D3DBlitLoops_SurfaceToSwBlit(JNIEnv *env, D3DContext *d3dc, width = srcInfo.bounds.x2 - srcInfo.bounds.x1; height = srcInfo.bounds.y2 - srcInfo.bounds.y1; - J2dTraceLn4(J2D_TRACE_VERBOSE, " sx=%d sy=%d w=%d h=%d", - srcx, srcy, width, height); - J2dTraceLn2(J2D_TRACE_VERBOSE, " dx=%d dy=%d", - dstx, dsty); + J2dTraceLn(J2D_TRACE_VERBOSE, " sx=%d sy=%d w=%d h=%d", + srcx, srcy, width, height); + J2dTraceLn(J2D_TRACE_VERBOSE, " dx=%d dy=%d", + dstx, dsty); d3dc->UpdateState(STATE_OTHEROP); @@ -961,10 +961,10 @@ D3DBlitLoops_CopyArea(JNIEnv *env, RETURN_STATUS_IF_NULL(dstOps, E_FAIL); RETURN_STATUS_IF_NULL(dstOps->pResource, E_FAIL); - J2dTraceLn4(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", - x, y, width, height); - J2dTraceLn2(J2D_TRACE_VERBOSE, " dx=%d dy=%d", - dx, dy); + J2dTraceLn(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", + x, y, width, height); + J2dTraceLn(J2D_TRACE_VERBOSE, " dx=%d dy=%d", + dx, dy); IDirect3DDevice9 *pd3dDevice = d3dc->Get3DDevice(); RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL); diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBufImgOps.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBufImgOps.cpp index b8b1ec892c1..f1de279014c 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBufImgOps.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DBufImgOps.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,9 +56,9 @@ D3DBufImgOps_EnableConvolveOp(D3DContext *d3dc, jlong pSrcOps, jint i, j, kIndex; jint flags = 0; - J2dTraceLn2(J2D_TRACE_INFO, - "D3DBufImgOps_EnableConvolveOp: kernelW=%d kernelH=%d", - kernelWidth, kernelHeight); + J2dTraceLn(J2D_TRACE_INFO, + "D3DBufImgOps_EnableConvolveOp: kernelW=%d kernelH=%d", + kernelWidth, kernelHeight); RETURN_STATUS_IF_NULL(d3dc, E_FAIL); RETURN_STATUS_IF_NULL(srcOps, E_FAIL); @@ -204,9 +204,9 @@ D3DBufImgOps_EnableLookupOp(D3DContext *d3dc, for (i = 0; i < 4; i++) { bands[i] = NULL; } - J2dTraceLn4(J2D_TRACE_INFO, - "D3DBufImgOps_EnableLookupOp: short=%d num=%d len=%d off=%d", - shortData, numBands, bandLength, offset); + J2dTraceLn(J2D_TRACE_INFO, + "D3DBufImgOps_EnableLookupOp: short=%d num=%d len=%d off=%d", + shortData, numBands, bandLength, offset); RETURN_STATUS_IF_NULL(d3dc, E_FAIL); diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DContext.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DContext.cpp index da263367ad9..a91cb58f875 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DContext.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DContext.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -213,7 +213,7 @@ D3DContext::CreateInstance(IDirect3D9 *pd3d9, UINT adapter, D3DContext **ppCtx) D3DContext::D3DContext(IDirect3D9 *pd3d, UINT adapter) { J2dTraceLn(J2D_TRACE_INFO, "D3DContext::D3DContext"); - J2dTraceLn1(J2D_TRACE_VERBOSE, " pd3d=0x%x", pd3d); + J2dTraceLn(J2D_TRACE_VERBOSE, " pd3d=0x%x", pd3d); pd3dObject = pd3d; pd3dDevice = NULL; adapterOrdinal = adapter; @@ -283,9 +283,9 @@ void D3DContext::ReleaseDefPoolResources() void D3DContext::ReleaseContextResources() { - J2dTraceLn1(J2D_TRACE_INFO, - "D3DContext::ReleaseContextResources: pd3dDevice = 0x%x", - pd3dDevice); + J2dTraceLn(J2D_TRACE_INFO, + "D3DContext::ReleaseContextResources: pd3dDevice = 0x%x", + pd3dDevice); ReleaseDefPoolResources(); @@ -309,9 +309,9 @@ void D3DContext::ReleaseContextResources() } D3DContext::~D3DContext() { - J2dTraceLn2(J2D_TRACE_INFO, - "~D3DContext: pd3dDevice=0x%x, pd3dObject =0x%x", - pd3dDevice, pd3dObject); + J2dTraceLn(J2D_TRACE_INFO, + "~D3DContext: pd3dDevice=0x%x, pd3dObject =0x%x", + pd3dDevice, pd3dObject); ReleaseContextResources(); SAFE_RELEASE(pd3dDevice); } @@ -323,8 +323,8 @@ D3DContext::InitDevice(IDirect3DDevice9 *pd3dDevice) pd3dDevice->GetDeviceCaps(&devCaps); - J2dRlsTraceLn1(J2D_TRACE_INFO, - "D3DContext::InitDevice: device %d", adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_INFO, + "D3DContext::InitDevice: device %d", adapterOrdinal); // disable some of the unneeded and costly d3d functionality pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); @@ -423,9 +423,9 @@ D3DContext::InitDevice(IDirect3DDevice9 *pd3dDevice) bBeginScenePending = FALSE; - J2dRlsTraceLn1(J2D_TRACE_INFO, - "D3DContext::InitDefice: successfully initialized device %d", - adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_INFO, + "D3DContext::InitDefice: successfully initialized device %d", + adapterOrdinal); return res; } @@ -440,13 +440,13 @@ D3DContext::CheckAndResetDevice() if (pd3dDevice != NULL) { if (FAILED(res = pd3dDevice->TestCooperativeLevel())) { if (res == D3DERR_DEVICELOST) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " device %d is still lost", - adapterOrdinal); + J2dTraceLn(J2D_TRACE_VERBOSE, " device %d is still lost", + adapterOrdinal); // nothing to be done here, wait for D3DERR_DEVICENOTRESET return res; } else if (res == D3DERR_DEVICENOTRESET) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " device %d needs to be reset", - adapterOrdinal); + J2dTraceLn(J2D_TRACE_VERBOSE, " device %d needs to be reset", + adapterOrdinal); res = ResetContext(); } else { // some unexpected error @@ -454,8 +454,8 @@ D3DContext::CheckAndResetDevice() "unknown error %x from TestCooperativeLevel"); } } else { - J2dTraceLn1(J2D_TRACE_VERBOSE, " device %d is not lost", - adapterOrdinal); + J2dTraceLn(J2D_TRACE_VERBOSE, " device %d is not lost", + adapterOrdinal); } } else { J2dTraceLn(J2D_TRACE_VERBOSE, " null device"); @@ -491,8 +491,8 @@ D3DContext::ResetContext() HRESULT D3DContext::ConfigureContext(D3DPRESENT_PARAMETERS *pNewParams) { - J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DContext::ConfigureContext device %d", - adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_INFO, "D3DContext::ConfigureContext device %d", + adapterOrdinal); HRESULT res = S_OK; D3DFORMAT stencilFormat; HWND focusHWND = D3DPipelineManager::GetInstance()->GetCurrentFocusWindow(); @@ -516,7 +516,7 @@ D3DContext::ConfigureContext(D3DPRESENT_PARAMETERS *pNewParams) // do not set device window in the windowed mode, we use additional // swap chains for rendering, the default chain is not used. otherwise // our scratch focus window will be made visible - J2dTraceLn1(J2D_TRACE_VERBOSE, " windowed=%d",pNewParams->Windowed); + J2dTraceLn(J2D_TRACE_VERBOSE, " windowed=%d",pNewParams->Windowed); if (pNewParams->Windowed) { pNewParams->hDeviceWindow = (HWND)0; } @@ -571,9 +571,8 @@ D3DContext::ConfigureContext(D3DPRESENT_PARAMETERS *pNewParams) "D3DContext::ConfigureContext: could not reset the device"); return res; } - J2dRlsTraceLn1(J2D_TRACE_INFO, - "D3DContext::ConfigureContext: successfully reset device: %d", - adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_INFO, "D3DContext::ConfigureContext: " \ + "successfully reset device: %d", adapterOrdinal); } else { D3DCAPS9 d3dCaps; DWORD dwBehaviorFlags; @@ -622,9 +621,8 @@ D3DContext::ConfigureContext(D3DPRESENT_PARAMETERS *pNewParams) "D3DContext::ConfigureContext: error creating d3d device"); return res; } - J2dRlsTraceLn1(J2D_TRACE_INFO, - "D3DContext::ConfigureContext: successfully created device: %d", - adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_INFO, "D3DContext::ConfigureContext: " \ + "successfully created device: %d", adapterOrdinal); bIsHWRasterizer = (devType == D3DDEVTYPE_HAL); } @@ -646,8 +644,8 @@ D3DContext::ConfigureContext(D3DPRESENT_PARAMETERS *pNewParams) HRESULT D3DContext::InitContext() { - J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DContext::InitContext device %d", - adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_INFO, "D3DContext::InitContext device %d", + adapterOrdinal); D3DPRESENT_PARAMETERS params; ZeroMemory(¶ms, sizeof(D3DPRESENT_PARAMETERS)); @@ -791,9 +789,9 @@ D3DContext::SetRenderTarget(IDirect3DSurface9 *pSurface) D3DSURFACE_DESC descNew; IDirect3DSurface9 *pCurrentTarget; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DContext::SetRenderTarget: pSurface=0x%x", - pSurface); + J2dTraceLn(J2D_TRACE_INFO, + "D3DContext::SetRenderTarget: pSurface=0x%x", + pSurface); RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL); RETURN_STATUS_IF_NULL(pSurface, E_FAIL); @@ -829,7 +827,7 @@ D3DContext::SetRenderTarget(IDirect3DSurface9 *pSurface) (float)descNew.Height); pd3dDevice->SetTransform(D3DTS_PROJECTION, &tx); - J2dTraceLn1(J2D_TRACE_VERBOSE, " current render target=0x%x", pSurface); + J2dTraceLn(J2D_TRACE_VERBOSE, " current render target=0x%x", pSurface); return res; } @@ -900,14 +898,14 @@ D3DContext::SetTransform(jdouble m00, jdouble m10, tx._42 = -0.5f; D3DUtils_2DConcatenateM(&tx, &tx1); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " %5f %5f %5f %5f", tx._11, tx._12, tx._13, tx._14); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " %5f %5f %5f %5f", tx._21, tx._22, tx._23, tx._24); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " %5f %5f %5f %5f", tx._31, tx._32, tx._33, tx._34); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " %5f %5f %5f %5f", tx._41, tx._42, tx._43, tx._44); + J2dTraceLn(J2D_TRACE_VERBOSE, + " %5f %5f %5f %5f", tx._11, tx._12, tx._13, tx._14); + J2dTraceLn(J2D_TRACE_VERBOSE, + " %5f %5f %5f %5f", tx._21, tx._22, tx._23, tx._24); + J2dTraceLn(J2D_TRACE_VERBOSE, + " %5f %5f %5f %5f", tx._31, tx._32, tx._33, tx._34); + J2dTraceLn(J2D_TRACE_VERBOSE, + " %5f %5f %5f %5f", tx._41, tx._42, tx._43, tx._44); if (FAILED(res = pd3dDevice->SetTransform(D3DTS_WORLD, &tx))) { DebugPrintD3DError(res, "D3DContext::SetTransform failed"); } @@ -924,9 +922,9 @@ D3DContext::SetRectClip(int x1, int y1, int x2, int y2) IDirect3DSurface9 *pCurrentTarget; J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SetRectClip"); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " x1=%-4d y1=%-4d x2=%-4d y2=%-4d", - x1, y1, x2, y2); + J2dTraceLn(J2D_TRACE_VERBOSE, + " x1=%-4d y1=%-4d x2=%-4d y2=%-4d", + x1, y1, x2, y2); RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL); @@ -962,9 +960,9 @@ D3DContext::SetRectClip(int x1, int y1, int x2, int y2) res = pd3dDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE); } else { DebugPrintD3DError(res, "Error setting scissor rect"); - J2dRlsTraceLn4(J2D_TRACE_ERROR, - " x1=%-4d y1=%-4d x2=%-4d y2=%-4d", - x1, y1, x2, y2); + J2dRlsTraceLn(J2D_TRACE_ERROR, + " x1=%-4d y1=%-4d x2=%-4d y2=%-4d", + x1, y1, x2, y2); } return res; @@ -1108,9 +1106,9 @@ D3DContext::UploadTileToTexture(D3DResource *pTextureRes, void *pixels, jint pixelsTouchedL = 0, pixelsTouchedR = 0; J2dTraceLn(J2D_TRACE_INFO, "D3DContext::UploadTileToTexture"); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " rect={%-4d, %-4d, %-4d, %-4d}", - r.left, r.top, r.right, r.bottom); + J2dTraceLn(J2D_TRACE_VERBOSE, + " rect={%-4d, %-4d, %-4d, %-4d}", + r.left, r.top, r.right, r.bottom); if (pDesc->Usage == D3DUSAGE_DYNAMIC) { // it is safe to lock with discard because we don't care about the @@ -1300,9 +1298,9 @@ HRESULT D3DContext::SetAlphaComposite(jint rule, jfloat ea, jint flags) { HRESULT res; - J2dTraceLn3(J2D_TRACE_INFO, - "D3DContext::SetAlphaComposite: rule=%-1d ea=%f flags=%d", - rule, ea, flags); + J2dTraceLn(J2D_TRACE_INFO, + "D3DContext::SetAlphaComposite: rule=%-1d ea=%f flags=%d", + rule, ea, flags); RETURN_STATUS_IF_NULL(pd3dDevice, E_FAIL); @@ -1316,12 +1314,12 @@ D3DContext::SetAlphaComposite(jint rule, jfloat ea, jint flags) (ea == 1.0f) && (flags & D3DC_SRC_IS_OPAQUE)) { - J2dTraceLn1(J2D_TRACE_VERBOSE, - " disabling alpha comp rule=%-1d ea=1.0 src=opq)", rule); + J2dTraceLn(J2D_TRACE_VERBOSE, + " disabling alpha comp rule=%-1d ea=1.0 src=opq)", rule); pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); } else { - J2dTraceLn2(J2D_TRACE_VERBOSE, - " enabling alpha comp (rule=%-1d ea=%f)", rule, ea); + J2dTraceLn(J2D_TRACE_VERBOSE, + " enabling alpha comp (rule=%-1d ea=%f)", rule, ea); pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); pd3dDevice->SetRenderState(D3DRS_SRCBLEND, @@ -1362,7 +1360,7 @@ D3DContext::UpdateTextureTransforms(DWORD dwSamplerToUpdate) // update only given sampler, dwMaxSampler will be set to it as well dwSampler = dwSamplerToUpdate; dwMaxSampler = dwSamplerToUpdate; - J2dTraceLn1(J2D_TRACE_INFO, "D3DContext::UpdateTextureTransforms: "\ + J2dTraceLn(J2D_TRACE_INFO, "D3DContext::UpdateTextureTransforms: "\ "updating sampler %d", dwSampler); } @@ -1376,14 +1374,14 @@ D3DContext::UpdateTextureTransforms(DWORD dwSamplerToUpdate) D3DSURFACE_DESC texDesc; pd3dDevice->GetTransform(D3DTS_WORLD, &tx); - J2dTraceLn4(10, - " %5f %5f %5f %5f", tx._11, tx._12, tx._13, tx._14); - J2dTraceLn4(10, - " %5f %5f %5f %5f", tx._21, tx._22, tx._23, tx._24); - J2dTraceLn4(10, - " %5f %5f %5f %5f", tx._31, tx._32, tx._33, tx._34); - J2dTraceLn4(10, - " %5f %5f %5f %5f", tx._41, tx._42, tx._43, tx._44); + J2dTraceLn(J2D_TRACE_VERBOSE2, + " %5f %5f %5f %5f", tx._11, tx._12, tx._13, tx._14); + J2dTraceLn(J2D_TRACE_VERBOSE2, + " %5f %5f %5f %5f", tx._21, tx._22, tx._23, tx._24); + J2dTraceLn(J2D_TRACE_VERBOSE2, + " %5f %5f %5f %5f", tx._31, tx._32, tx._33, tx._34); + J2dTraceLn(J2D_TRACE_VERBOSE2, + " %5f %5f %5f %5f", tx._41, tx._42, tx._43, tx._44); // this formula works for scales and flips if (tx._11 == 0.0f) { @@ -1403,8 +1401,8 @@ D3DContext::UpdateTextureTransforms(DWORD dwSamplerToUpdate) // transform. mt._31 = (1.0f / (2.0f * texDesc.Width * tx._11)); mt._32 = (1.0f / (2.0f * texDesc.Height * tx._22)); - J2dTraceLn2(J2D_TRACE_VERBOSE, " offsets: tx=%f ty=%f", - mt._31, mt._32); + J2dTraceLn(J2D_TRACE_VERBOSE, " offsets: tx=%f ty=%f", + mt._31, mt._32); pd3dDevice->SetTextureStageState(dwSampler, D3DTSS_TEXTURETRANSFORMFLAGS, @@ -1436,16 +1434,16 @@ D3DContext::SetTexture(IDirect3DTexture9 *pTexture, DWORD dwSampler) J2dTraceLn(J2D_TRACE_INFO, "D3DContext::SetTexture"); if (dwSampler < 0 || dwSampler > MAX_USED_TEXTURE_SAMPLER) { - J2dTraceLn1(J2D_TRACE_ERROR, - "D3DContext::SetTexture: incorrect sampler: %d", dwSampler); + J2dTraceLn(J2D_TRACE_ERROR, + "D3DContext::SetTexture: incorrect sampler: %d", dwSampler); return E_FAIL; } if (lastTexture[dwSampler] != pTexture) { if (FAILED(res = FlushVertexQueue())) { return res; } - J2dTraceLn2(J2D_TRACE_VERBOSE, - " new texture=0x%x on sampler %d", pTexture, dwSampler); + J2dTraceLn(J2D_TRACE_VERBOSE, + " new texture=0x%x on sampler %d", pTexture, dwSampler); res = pd3dDevice->SetTexture(dwSampler, pTexture); if (SUCCEEDED(res)) { lastTexture[dwSampler] = pTexture; @@ -1589,9 +1587,9 @@ IDirect3DPixelShader9 *D3DContext::CreateFragmentProgram(DWORD **shaders, DWORD *sourceCode; IDirect3DPixelShader9 *pProgram; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DContext::CreateFragmentProgram: flags=%d", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "D3DContext::CreateFragmentProgram: flags=%d", + flags); sourceCode = shaders[flags]; if (FAILED(pd3dDevice->CreatePixelShader(sourceCode, &pProgram))) { @@ -1782,7 +1780,7 @@ BOOL D3DContext::IsOpaqueRTTSupported() HRESULT D3DContext::InitContextCaps() { J2dTraceLn(J2D_TRACE_INFO, "D3DContext::InitContextCaps"); - J2dTraceLn1(J2D_TRACE_VERBOSE, " caps for adapter %d :", adapterOrdinal); + J2dTraceLn(J2D_TRACE_VERBOSE, " caps for adapter %d :", adapterOrdinal); if (pd3dDevice == NULL || pd3dObject == NULL) { contextCaps = CAPS_EMPTY; diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGlyphCache.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGlyphCache.cpp index d7eb4efd37a..a2d09a75bfd 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGlyphCache.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGlyphCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,7 @@ D3DGlyphCache::CreateInstance(D3DContext *pCtx, GlyphCacheType gcType, D3DGlyphCache::D3DGlyphCache(GlyphCacheType type) { - J2dTraceLn1(J2D_TRACE_INFO, "D3DGlyphCache::D3DGlyphCache gcType=%d", type); + J2dTraceLn(J2D_TRACE_INFO, "D3DGlyphCache::D3DGlyphCache gcType=%d", type); pCtx = NULL; gcType = type; @@ -90,7 +90,7 @@ D3DGlyphCache::Init(D3DContext *pCtx) RETURN_STATUS_IF_NULL(pCtx, E_FAIL); - J2dTraceLn1(J2D_TRACE_INFO, "D3DGlyphCache::Init pCtx=%x", pCtx); + J2dTraceLn(J2D_TRACE_INFO, "D3DGlyphCache::Init pCtx=%x", pCtx); this->pCtx = pCtx; diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGraphicsDevice.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGraphicsDevice.cpp index cd0295d758d..fa7cbc736ca 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGraphicsDevice.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DGraphicsDevice.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ JNIEXPORT jboolean JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_initD3D jboolean result = D3DInitializer::GetInstance().EnsureInited() ? JNI_TRUE : JNI_FALSE; - J2dTraceLn1(J2D_TRACE_INFO, "D3DGD_initD3D: result=%x", result); + J2dTraceLn(J2D_TRACE_INFO, "D3DGD_initD3D: result=%x", result); return result; } @@ -94,7 +94,7 @@ JNIEXPORT jstring JNICALL Java_sun_java2d_d3d_D3DGraphicsDevice_getDeviceIdNativ // in the buffer so we have to make sure it is null terminated pAdapterId[len-1] = (WCHAR)0; - J2dTraceLn1(J2D_TRACE_VERBOSE, " id=%S", pAdapterId); + J2dTraceLn(J2D_TRACE_VERBOSE, " id=%S", pAdapterId); jstring ret = JNU_NewStringPlatform(env, pAdapterId); @@ -123,7 +123,7 @@ Java_sun_java2d_d3d_D3DGraphicsDevice_getDeviceCapsNative adapter = pMgr->GetAdapterOrdinalForScreen(gdiScreen); if (FAILED(pMgr->GetD3DContext(adapter, &pCtx))) { - J2dRlsTraceLn1(J2D_TRACE_ERROR, + J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DGD_getDeviceCapsNative: device %d disabled", adapter); return CAPS_EMPTY; } @@ -318,17 +318,17 @@ Java_sun_java2d_d3d_D3DGraphicsDevice_configDisplayModeNative return; } } else { - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DGD_configDisplayModeNative: unsupported depth: %d", - bitDepth); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DGD_configDisplayModeNative: unsupported depth: %d", + bitDepth); return; } - J2dTraceLn4(J2D_TRACE_VERBOSE, " changing to dm: %dx%dx%d@%d", - newParams.BackBufferWidth, newParams.BackBufferHeight, - bitDepth, refreshRate); - J2dTraceLn1(J2D_TRACE_VERBOSE, " selected backbuffer format: %d", - newParams.BackBufferFormat); + J2dTraceLn(J2D_TRACE_VERBOSE, " changing to dm: %dx%dx%d@%d", + newParams.BackBufferWidth, newParams.BackBufferHeight, + bitDepth, refreshRate); + J2dTraceLn(J2D_TRACE_VERBOSE, " selected backbuffer format: %d", + newParams.BackBufferFormat); res = pCtx->ConfigureContext(&newParams); if (SUCCEEDED(res)) { @@ -370,9 +370,9 @@ Java_sun_java2d_d3d_D3DGraphicsDevice_getCurrentDisplayModeNative case D3DFMT_R5G6B5: case D3DFMT_X1R5G5B5: bitDepth = 16; break; } - J2dTraceLn4(J2D_TRACE_VERBOSE, - " current dm: %dx%dx%d@%d", - mode.Width, mode.Height, bitDepth, mode.RefreshRate); + J2dTraceLn(J2D_TRACE_VERBOSE, + " current dm: %dx%dx%d@%d", + mode.Width, mode.Height, bitDepth, mode.RefreshRate); ret = CreateDisplayMode(env, mode.Width, mode.Height, bitDepth, mode.RefreshRate); } @@ -418,8 +418,8 @@ Java_sun_java2d_d3d_D3DGraphicsDevice_enumDisplayModesNative case D3DFMT_R5G6B5: case D3DFMT_X1R5G5B5: bitDepth = 16; break; } - J2dTraceLn4(J2D_TRACE_VERBOSE, " found dm: %dx%dx%d@%d", - mode.Width, mode.Height, bitDepth,mode.RefreshRate); + J2dTraceLn(J2D_TRACE_VERBOSE, " found dm: %dx%dx%d@%d", + mode.Width, mode.Height, bitDepth,mode.RefreshRate); addDisplayMode(env, arrayList, mode.Width, mode.Height, bitDepth, mode.RefreshRate); } @@ -457,7 +457,7 @@ Java_sun_java2d_d3d_D3DGraphicsDevice_getAvailableAcceleratedMemoryNative RETURN_STATUS_IF_NULL(pd3dDevice = pCtx->Get3DDevice(), 0L); UINT mem = pd3dDevice->GetAvailableTextureMem(); - J2dTraceLn1(J2D_TRACE_VERBOSE, " available memory=%d", mem); + J2dTraceLn(J2D_TRACE_VERBOSE, " available memory=%d", mem); return mem; } diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DMaskCache.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DMaskCache.cpp index 74ff8e64664..c0d6d914173 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DMaskCache.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DMaskCache.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,7 @@ D3DMaskCache::~D3DMaskCache() HRESULT D3DMaskCache::Init(D3DContext *pCtx) { - J2dTraceLn1(J2D_TRACE_INFO, "D3DMaskCache::Init pCtx=%x", pCtx); + J2dTraceLn(J2D_TRACE_INFO, "D3DMaskCache::Init pCtx=%x", pCtx); this->pCtx = pCtx; this->maskCacheIndex = 0; return S_OK; @@ -103,8 +103,8 @@ HRESULT D3DMaskCache::AddMaskQuad(int srcx, int srcy, float tx1, ty1, tx2, ty2; float dx1, dy1, dx2, dy2; - J2dTraceLn1(J2D_TRACE_INFO, "D3DVertexCacher::AddMaskQuad: %d", - maskCacheIndex); + J2dTraceLn(J2D_TRACE_INFO, "D3DVertexCacher::AddMaskQuad: %d", + maskCacheIndex); if (maskCacheIndex >= D3D_MASK_CACHE_MAX_INDEX || pCtx->pVCacher->GetFreeVertices() < 6) diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DMaskFill.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DMaskFill.cpp index 6a380c7df79..59416b32152 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DMaskFill.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DMaskFill.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,9 +54,9 @@ D3DMaskFill_MaskFill(D3DContext *d3dc, RETURN_STATUS_IF_NULL(d3dc, E_FAIL); - J2dTraceLn4(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", x, y, w, h); - J2dTraceLn2(J2D_TRACE_VERBOSE, " maskoff=%d maskscan=%d", - maskoff, maskscan); + J2dTraceLn(J2D_TRACE_VERBOSE, " x=%d y=%d w=%d h=%d", x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, " maskoff=%d maskscan=%d", + maskoff, maskscan); { D3DMaskCache *maskCache = d3dc->GetMaskCache(); diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPaints.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPaints.cpp index 8ed5e2388b8..c725da89bc1 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPaints.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPaints.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,7 @@ D3DPaints_ResetPaint(D3DContext *d3dc) RETURN_STATUS_IF_NULL(d3dc, E_FAIL); paintState = d3dc->GetPaintState(); - J2dTraceLn1(J2D_TRACE_VERBOSE, " state=%d", paintState); + J2dTraceLn(J2D_TRACE_VERBOSE, " state=%d", paintState); res = d3dc->UpdateState(STATE_OTHEROP); @@ -89,7 +89,7 @@ D3DPaints_SetColor(D3DContext *d3dc, jint pixel) { HRESULT res = S_OK; - J2dTraceLn1(J2D_TRACE_INFO, "D3DPaints_SetColor: pixel=%08x", pixel); + J2dTraceLn(J2D_TRACE_INFO, "D3DPaints_SetColor: pixel=%08x", pixel); RETURN_STATUS_IF_NULL(d3dc, E_FAIL); diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPipeline.h b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPipeline.h index 5d9332e954b..135f09d79b7 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPipeline.h +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPipeline.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ #include "Trace.h" #define DebugPrintD3DError(res, msg) \ - J2dTraceLn1(J2D_TRACE_ERROR, "D3D Error: " msg " res=%d", res) + J2dTraceLn(J2D_TRACE_ERROR, "D3D Error: " msg " res=%d", res) // some helper macros #define SAFE_RELEASE(RES) \ @@ -60,7 +60,7 @@ do { \ #define SAFE_PRINTLN(RES) \ do { \ if ((RES)!= NULL) { \ - J2dTraceLn1(J2D_TRACE_VERBOSE, " " #RES "=0x%x", (RES)); \ + J2dTraceLn(J2D_TRACE_VERBOSE, " " #RES "=0x%x", (RES)); \ } else { \ J2dTraceLn(J2D_TRACE_VERBOSE, " " #RES "=NULL"); \ } \ @@ -76,8 +76,8 @@ do { \ */ #define ACT_IF_NULL(ACTION, value) \ if ((value) == NULL) { \ - J2dTraceLn3(J2D_TRACE_ERROR, \ - "%s is null in %s:%d", #value, __FILE__, __LINE__); \ + J2dTraceLn(J2D_TRACE_ERROR, \ + "%s is null in %s:%d", #value, __FILE__, __LINE__); \ ACTION; \ } else do { } while (0) #define RETURN_IF_NULL(value) ACT_IF_NULL(return, value) diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPipelineManager.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPipelineManager.cpp index 27bf3e39d08..3048f12914d 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPipelineManager.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DPipelineManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,9 +59,9 @@ D3DPipelineManager * D3DPipelineManager::CreateInstance(void) // this should never happen so to be on the safe side do not // use this unexpected pointer, do not try to release it, just null // it out and fail safely - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DPPLM::CreateInstance: unexpected instance: 0x%x,"\ - " abort.", pMgr); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DPPLM::CreateInstance: unexpected instance: 0x%x,"\ + " abort.", pMgr); pMgr = NULL; } return pMgr; @@ -201,7 +201,7 @@ HRESULT D3DPipelineManager::HandleAdaptersChange(HMONITOR *pHMONITORs, UINT monN J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::HandleAdaptersChange"); if (monNum != pMgr->adapterCount) { - J2dTraceLn2(J2D_TRACE_VERBOSE, + J2dTraceLn(J2D_TRACE_VERBOSE, " number of adapters changed (old=%d, new=%d)", pMgr->adapterCount, monNum); bResetD3D = TRUE; @@ -209,23 +209,23 @@ HRESULT D3DPipelineManager::HandleAdaptersChange(HMONITOR *pHMONITORs, UINT monN for (UINT i = 0; i < pMgr->adapterCount; i++) { HMONITOR hMon = pMgr->pd3d9->GetAdapterMonitor(i); if (hMon == (HMONITOR)0x0) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " adapter %d: removed", i); + J2dTraceLn(J2D_TRACE_VERBOSE, " adapter %d: removed", i); bResetD3D = TRUE; break; } bFound = FALSE; for (UINT mon = 0; mon < monNum; mon++) { if (pHMONITORs[mon] == hMon) { - J2dTraceLn3(J2D_TRACE_VERBOSE, - " adapter %d: found hmnd[%d]=0x%x", i, mon, hMon); + J2dTraceLn(J2D_TRACE_VERBOSE, + " adapter %d: found hmnd[%d]=0x%x", i, mon, hMon); bFound = TRUE; break; } } if (!bFound) { - J2dTraceLn2(J2D_TRACE_VERBOSE, - " adapter %d: could not find hmnd=0x%x "\ - "in the list of new hmnds", i, hMon); + J2dTraceLn(J2D_TRACE_VERBOSE, + " adapter %d: could not find hmnd=0x%x "\ + "in the list of new hmnds", i, hMon); bResetD3D = TRUE; break; } @@ -276,8 +276,8 @@ HRESULT D3DPipelineManager::HandleLostDevices() if (pAdapters != NULL) { for (UINT i = 0; i < adapterCount; i++) { if (pAdapters[i].pd3dContext != NULL) { - J2dTraceLn1(J2D_TRACE_VERBOSE, - " HandleLostDevices: checking adapter %d", i); + J2dTraceLn(J2D_TRACE_VERBOSE, + " HandleLostDevices: checking adapter %d", i); D3DContext *d3dc = pAdapters[i].pd3dContext; if (FAILED(d3dc->CheckAndResetDevice())) { bAllClear = FALSE; @@ -374,9 +374,9 @@ D3DPipelineManager::GDICheckForBadHardware() int args2 = swscanf(deviceId, L"%X", &dwDId); if (args1 == 1 && args2 == 1) { - J2dTraceLn2(J2D_TRACE_VERBOSE, - " device: vendorID=0x%04x, deviceId=0x%04x", - dwVId, dwDId); + J2dTraceLn(J2D_TRACE_VERBOSE, + " device: vendorID=0x%04x, deviceId=0x%04x", + dwVId, dwDId); // since we don't have a driver version here we will // just ask to ignore the version for now; bad hw // entries with specific drivers information will be @@ -450,16 +450,16 @@ BOOL D3DPPLM_OsVersionMatches(USHORT osInfo) { J2dRlsTrace(J2D_TRACE_INFO, "Pro\n"); } } else { - J2dRlsTrace2(J2D_TRACE_INFO, + J2dRlsTrace(J2D_TRACE_INFO, "OS_UNKNOWN: dwMajorVersion=%d dwMinorVersion=%d\n", - osvi.dwMajorVersion, osvi.dwMinorVersion); + osvi.dwMajorVersion, osvi.dwMinorVersion); currentOS = OS_UNKNOWN; } } else { if (bVersOk) { - J2dRlsTrace2(J2D_TRACE_INFO, - "OS_UNKNOWN: dwPlatformId=%d dwMajorVersion=%d\n", - osvi.dwPlatformId, osvi.dwMajorVersion); + J2dRlsTrace(J2D_TRACE_INFO, + "OS_UNKNOWN: dwPlatformId=%d dwMajorVersion=%d\n", + osvi.dwPlatformId, osvi.dwMajorVersion); } else { J2dRlsTrace(J2D_TRACE_INFO,"OS_UNKNOWN: GetVersionEx failed\n"); } @@ -492,21 +492,21 @@ D3DPipelineManager::CheckForBadHardware(DWORD vId, DWORD dId, LONGLONG version) if (D3DPPLM_OsVersionMatches(osInfo) && (goodVersion == NO_VERSION || version < goodVersion)) { - J2dRlsTraceLn2(J2D_TRACE_ERROR, - "D3DPPLM::CheckForBadHardware: found matching "\ - "hardware: VendorId=0x%04x DeviceId=0x%04x", - vendorId, deviceId); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DPPLM::CheckForBadHardware: found matching "\ + "hardware: VendorId=0x%04x DeviceId=0x%04x", + vendorId, deviceId); if (goodVersion != NO_VERSION) { // this was a match by the driver version LARGE_INTEGER li; li.QuadPart = goodVersion; J2dRlsTraceLn(J2D_TRACE_ERROR, " bad driver found, device disabled"); - J2dRlsTraceLn4(J2D_TRACE_ERROR, - " update your driver to at "\ - "least version %d.%d.%d.%d", - HIWORD(li.HighPart), LOWORD(li.HighPart), - HIWORD(li.LowPart), LOWORD(li.LowPart)); + J2dRlsTraceLn(J2D_TRACE_ERROR, + " update your driver to at "\ + "least version %d.%d.%d.%d", + HIWORD(li.HighPart), LOWORD(li.HighPart), + HIWORD(li.LowPart), LOWORD(li.LowPart)); } else { // this was a match by the device (no good driver for this // device) @@ -542,39 +542,39 @@ HRESULT D3DPipelineManager::CheckAdaptersInfo() continue; } - J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Ordinal : %d", Adapter); - J2dRlsTraceLn1(J2D_TRACE_INFO, "Adapter Handle : 0x%x", - pd3d9->GetAdapterMonitor(Adapter)); - J2dRlsTraceLn1(J2D_TRACE_INFO, "Description : %s", - aid.Description); - J2dRlsTraceLn2(J2D_TRACE_INFO, "GDI Name, Driver : %s, %s", - aid.DeviceName, aid.Driver); - J2dRlsTraceLn1(J2D_TRACE_INFO, "Vendor Id : 0x%04x", - aid.VendorId); - J2dRlsTraceLn1(J2D_TRACE_INFO, "Device Id : 0x%04x", - aid.DeviceId); - J2dRlsTraceLn1(J2D_TRACE_INFO, "SubSys Id : 0x%x", - aid.SubSysId); - J2dRlsTraceLn4(J2D_TRACE_INFO, "Driver Version : %d.%d.%d.%d", - HIWORD(aid.DriverVersion.HighPart), - LOWORD(aid.DriverVersion.HighPart), - HIWORD(aid.DriverVersion.LowPart), - LOWORD(aid.DriverVersion.LowPart)); - J2dRlsTrace3(J2D_TRACE_INFO, - "[I] GUID : {%08X-%04X-%04X-", - aid.DeviceIdentifier.Data1, - aid.DeviceIdentifier.Data2, - aid.DeviceIdentifier.Data3); - J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X-%02X%02X", - aid.DeviceIdentifier.Data4[0], - aid.DeviceIdentifier.Data4[1], - aid.DeviceIdentifier.Data4[2], - aid.DeviceIdentifier.Data4[3]); - J2dRlsTrace4(J2D_TRACE_INFO, "%02X%02X%02X%02X}\n", - aid.DeviceIdentifier.Data4[4], - aid.DeviceIdentifier.Data4[5], - aid.DeviceIdentifier.Data4[6], - aid.DeviceIdentifier.Data4[7]); + J2dRlsTraceLn(J2D_TRACE_INFO, "Adapter Ordinal : %d", Adapter); + J2dRlsTraceLn(J2D_TRACE_INFO, "Adapter Handle : 0x%x", + pd3d9->GetAdapterMonitor(Adapter)); + J2dRlsTraceLn(J2D_TRACE_INFO, "Description : %s", + aid.Description); + J2dRlsTraceLn(J2D_TRACE_INFO, "GDI Name, Driver : %s, %s", + aid.DeviceName, aid.Driver); + J2dRlsTraceLn(J2D_TRACE_INFO, "Vendor Id : 0x%04x", + aid.VendorId); + J2dRlsTraceLn(J2D_TRACE_INFO, "Device Id : 0x%04x", + aid.DeviceId); + J2dRlsTraceLn(J2D_TRACE_INFO, "SubSys Id : 0x%x", + aid.SubSysId); + J2dRlsTraceLn(J2D_TRACE_INFO, "Driver Version : %d.%d.%d.%d", + HIWORD(aid.DriverVersion.HighPart), + LOWORD(aid.DriverVersion.HighPart), + HIWORD(aid.DriverVersion.LowPart), + LOWORD(aid.DriverVersion.LowPart)); + J2dRlsTrace(J2D_TRACE_INFO, + "[I] GUID : {%08X-%04X-%04X-", + aid.DeviceIdentifier.Data1, + aid.DeviceIdentifier.Data2, + aid.DeviceIdentifier.Data3); + J2dRlsTrace(J2D_TRACE_INFO, "%02X%02X-%02X%02X", + aid.DeviceIdentifier.Data4[0], + aid.DeviceIdentifier.Data4[1], + aid.DeviceIdentifier.Data4[2], + aid.DeviceIdentifier.Data4[3]); + J2dRlsTrace(J2D_TRACE_INFO, "%02X%02X%02X%02X}\n", + aid.DeviceIdentifier.Data4[4], + aid.DeviceIdentifier.Data4[5], + aid.DeviceIdentifier.Data4[6], + aid.DeviceIdentifier.Data4[7]); if (FAILED(CheckForBadHardware(aid.VendorId, aid.DeviceId, aid.DriverVersion.QuadPart)) || @@ -612,9 +612,9 @@ D3DDEVTYPE D3DPipelineManager::SelectDeviceType() J2dRlsTrace(J2D_TRACE_WARNING, "nullref rasterizer selected"); dtype = D3DDEVTYPE_NULLREF; } else { - J2dRlsTrace1(J2D_TRACE_WARNING, - "unknown rasterizer: %s, only (ref|hal|nul) "\ - "supported, hal selected instead", pRas); + J2dRlsTrace(J2D_TRACE_WARNING, + "unknown rasterizer: %s, only (ref|hal|nul) "\ + "supported, hal selected instead", pRas); } J2dRlsTrace(J2D_TRACE_WARNING, "\n"); } @@ -624,10 +624,10 @@ D3DDEVTYPE D3DPipelineManager::SelectDeviceType() #define CHECK_CAP(FLAG, CAP) \ do { \ if (!((FLAG)&CAP)) { \ - J2dRlsTraceLn2(J2D_TRACE_ERROR, \ - "D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\ - "(cap %s not supported)", \ - adapter, #CAP); \ + J2dRlsTraceLn(J2D_TRACE_ERROR, \ + "D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\ + "(cap %s not supported)", \ + adapter, #CAP); \ return E_FAIL; \ } \ } while (0) @@ -684,14 +684,14 @@ HRESULT D3DPipelineManager::CheckDeviceCaps(UINT adapter) CHECK_CAP(d3dCaps.TextureOpCaps, D3DTEXOPCAPS_MODULATE); if (d3dCaps.PixelShaderVersion < D3DPS_VERSION(2,0) && !IsD3DForced()) { - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\ - "(pixel shaders 2.0 required)", adapter); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DPPLM::CheckDeviceCaps: adapter %d: Failed "\ + "(pixel shaders 2.0 required)", adapter); return E_FAIL; } - J2dRlsTraceLn1(J2D_TRACE_INFO, - "D3DPPLM::CheckDeviceCaps: adapter %d: Passed", adapter); + J2dRlsTraceLn(J2D_TRACE_INFO, + "D3DPPLM::CheckDeviceCaps: adapter %d: Passed", adapter); return S_OK; } @@ -706,9 +706,9 @@ HRESULT D3DPipelineManager::D3DEnabledOnAdapter(UINT adapter) res = pd3d9->CheckDeviceType(adapter, devType, dm.Format, dm.Format, TRUE); if (FAILED(res)) { - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DPPLM::D3DEnabledOnAdapter: no " \ - "suitable d3d device on adapter %d", adapter); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DPPLM::D3DEnabledOnAdapter: no " \ + "suitable d3d device on adapter %d", adapter); } return res; @@ -759,9 +759,9 @@ HWND D3DPipelineManager::CreateDefaultFocusWindow() { UINT adapterOrdinal = D3DADAPTER_DEFAULT; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DPPLM::CreateDefaultFocusWindow: adapter=%d", - adapterOrdinal); + J2dTraceLn(J2D_TRACE_INFO, + "D3DPPLM::CreateDefaultFocusWindow: adapter=%d", + adapterOrdinal); if (defaultFocusWindow != 0) { J2dRlsTraceLn(J2D_TRACE_WARNING, @@ -787,9 +787,10 @@ HWND D3DPipelineManager::CreateDefaultFocusWindow() mi.cbSize = sizeof(MONITORINFO); HMONITOR hMon = pd3d9->GetAdapterMonitor(adapterOrdinal); if (hMon == 0 || !GetMonitorInfo(hMon, (LPMONITORINFO)&mi)) { - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DPPLM::CreateDefaultFocusWindow: "\ - "error getting monitor info for adapter=%d", adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DPPLM::CreateDefaultFocusWindow: "\ + "error getting monitor info for adapter=%d", + adapterOrdinal); return 0; } @@ -800,9 +801,9 @@ HWND D3DPipelineManager::CreateDefaultFocusWindow() J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DPPLM::CreateDefaultFocusWindow: CreateWindow failed"); } else { - J2dTraceLn2(J2D_TRACE_INFO, - " Created default focus window %x for adapter %d", - hWnd, adapterOrdinal); + J2dTraceLn(J2D_TRACE_INFO, + " Created default focus window %x for adapter %d", + hWnd, adapterOrdinal); defaultFocusWindow = hWnd; } return hWnd; @@ -812,20 +813,20 @@ HWND D3DPipelineManager::GetCurrentFocusWindow() { J2dTraceLn(J2D_TRACE_INFO, "D3DPPLM::GetCurrentFocusWindow"); if (currentFSFocusAdapter < 0) { - J2dTraceLn1(J2D_TRACE_VERBOSE, - " no fs windows, using default focus window=0x%x", - defaultFocusWindow); + J2dTraceLn(J2D_TRACE_VERBOSE, + " no fs windows, using default focus window=0x%x", + defaultFocusWindow); return defaultFocusWindow; } - J2dTraceLn1(J2D_TRACE_VERBOSE, " using fs window=0x%x", - pAdapters[currentFSFocusAdapter].fsFocusWindow); + J2dTraceLn(J2D_TRACE_VERBOSE, " using fs window=0x%x", + pAdapters[currentFSFocusAdapter].fsFocusWindow); return pAdapters[currentFSFocusAdapter].fsFocusWindow; } HWND D3DPipelineManager::SetFSFocusWindow(UINT adapterOrdinal, HWND hWnd) { - J2dTraceLn2(J2D_TRACE_INFO,"D3DPPLM::SetFSFocusWindow hwnd=0x%x adapter=%d", - hWnd, adapterOrdinal); + J2dTraceLn(J2D_TRACE_INFO,"D3DPPLM::SetFSFocusWindow hwnd=0x%x adapter=%d", + hWnd, adapterOrdinal); HWND prev = pAdapters[adapterOrdinal].fsFocusWindow; pAdapters[adapterOrdinal].fsFocusWindow = hWnd; @@ -846,8 +847,8 @@ HWND D3DPipelineManager::SetFSFocusWindow(UINT adapterOrdinal, HWND hWnd) currentFSFocusAdapter = -1; for (i = 0; i < adapterCount; i++) { if (pAdapters[i].fsFocusWindow != 0) { - J2dTraceLn1(J2D_TRACE_VERBOSE, - " adapter %d is still in fs mode", i); + J2dTraceLn(J2D_TRACE_VERBOSE, + " adapter %d is still in fs mode", i); currentFSFocusAdapter = i; break; } @@ -868,9 +869,9 @@ HWND D3DPipelineManager::SetFSFocusWindow(UINT adapterOrdinal, HWND hWnd) } } } else { - J2dTraceLn1(J2D_TRACE_WARNING, - "D3DPM::SetFSFocusWindow: setting the fs "\ - "window again for adapter %d", adapterOrdinal); + J2dTraceLn(J2D_TRACE_WARNING, + "D3DPM::SetFSFocusWindow: setting the fs "\ + "window again for adapter %d", adapterOrdinal); } } } @@ -887,9 +888,9 @@ HRESULT D3DPipelineManager::GetD3DContext(UINT adapterOrdinal, pAdapters == NULL || pAdapters[adapterOrdinal].state == CONTEXT_INIT_FAILED) { - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DPPLM::GetD3DContext: invalid parameters or "\ - "failed init for adapter %d", adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DPPLM::GetD3DContext: invalid parameters or "\ + "failed init for adapter %d", adapterOrdinal); *ppd3dContext = NULL; return E_FAIL; } @@ -898,23 +899,24 @@ HRESULT D3DPipelineManager::GetD3DContext(UINT adapterOrdinal, D3DContext *pCtx = NULL; if (pAdapters[adapterOrdinal].pd3dContext != NULL) { - J2dTraceLn1(J2D_TRACE_ERROR, " non-null context in "\ - "uninitialized adapter %d", adapterOrdinal); + J2dTraceLn(J2D_TRACE_ERROR, " non-null context in "\ + "uninitialized adapter %d", adapterOrdinal); res = E_FAIL; } else { - J2dTraceLn1(J2D_TRACE_VERBOSE, - " initializing context for adapter %d",adapterOrdinal); + J2dTraceLn(J2D_TRACE_VERBOSE, + " initializing context for adapter %d",adapterOrdinal); if (SUCCEEDED(res = D3DEnabledOnAdapter(adapterOrdinal))) { res = D3DContext::CreateInstance(pd3d9, adapterOrdinal, &pCtx); if (FAILED(res)) { - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DPPLM::GetD3DContext: failed to create context "\ - "for adapter=%d", adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_ERROR, "D3DPPLM::GetD3DContext: "\ + "failed to create context "\ + "for adapter=%d", adapterOrdinal); } } else { - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DPPLM::GetContext: no d3d on adapter %d",adapterOrdinal); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DPPLM::GetContext: no d3d on adapter %d", + adapterOrdinal); } } pAdapters[adapterOrdinal].state = @@ -967,8 +969,8 @@ void D3DInitializer::InitImpl() void D3DInitializer::CleanImpl(bool reInit) { - J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DInitializer::CleanImpl (%s)", - reInit ? "RELAUNCH" : "normal"); + J2dRlsTraceLn(J2D_TRACE_INFO, "D3DInitializer::CleanImpl (%s)", + reInit ? "RELAUNCH" : "normal"); D3DPipelineManager::DeleteInstance(); if (bComInitialized) { CoUninitialize(); @@ -978,7 +980,7 @@ void D3DInitializer::CleanImpl(bool reInit) void D3DInitializer::D3DAdapterInitializer::InitImpl() { - J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) started", adapter); + J2dRlsTraceLn(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) started", adapter); D3DPipelineManager *pMgr = D3DPipelineManager::GetInstance(); if (pMgr == NULL) { @@ -988,7 +990,7 @@ void D3DInitializer::D3DAdapterInitializer::InitImpl() D3DContext *pd3dContext; pMgr->GetD3DContext(adapter, &pd3dContext); - J2dRlsTraceLn1(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) finished", adapter); + J2dRlsTraceLn(J2D_TRACE_INFO, "D3DAdapterInitializer::InitImpl(%d) finished", adapter); } void D3DInitializer::D3DAdapterInitializer::CleanImpl(bool reInit) diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DRenderQueue.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DRenderQueue.cpp index 5508409b530..2f69fd4269b 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DRenderQueue.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DRenderQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -67,8 +67,8 @@ D3DRQ_SwapBuffers(D3DPipelineManager *pMgr, D3DSDOps *d3dsdo, RECT srcRect, dstRect, *pSrcRect, *pDstRect; J2dTraceLn(J2D_TRACE_INFO, "D3DRQ_SwapBuffers"); - J2dTraceLn4(J2D_TRACE_VERBOSE, " x1=%d y1=%d x2=%d y2=%d", - x1, y1, x2, y2); + J2dTraceLn(J2D_TRACE_VERBOSE, " x1=%d y1=%d x2=%d y2=%d", + x1, y1, x2, y2); RETURN_STATUS_IF_NULL(d3dsdo, E_FAIL); RETURN_STATUS_IF_NULL(d3dsdo->pResource, E_FAIL); @@ -106,10 +106,10 @@ D3DRQ_SwapBuffers(D3DPipelineManager *pMgr, D3DSDOps *d3dsdo, int ww = r.right - r.left; int wh = r.bottom - r.top; if (ww != params.BackBufferWidth || wh != params.BackBufferHeight) { - J2dTraceLn4(J2D_TRACE_WARNING, - "D3DRQ_SwapBuffers: surface/window dimensions mismatch: "\ - "win: w=%d h=%d, bb: w=%d h=%d", - ww, wh, params.BackBufferWidth, params.BackBufferHeight); + J2dTraceLn(J2D_TRACE_WARNING, + "D3DRQ_SwapBuffers: surface/window dimensions mismatch: "\ + "win: w=%d h=%d, bb: w=%d h=%d", + ww, wh, params.BackBufferWidth, params.BackBufferHeight); return S_OK; } @@ -200,7 +200,7 @@ void D3DRQ_FlushBuffer(void *pParam) b = pFlush->buffer; limit = pFlush->limit; - J2dTraceLn1(J2D_TRACE_INFO, "D3DRQ_flushBuffer: limit=%d", limit); + J2dTraceLn(J2D_TRACE_INFO, "D3DRQ_flushBuffer: limit=%d", limit); end = b + limit; @@ -219,7 +219,7 @@ void D3DRQ_FlushBuffer(void *pParam) while (b < end) { jint opcode = NEXT_INT(b); - J2dTraceLn1(J2D_TRACE_VERBOSE, "D3DRQ_flushBuffer: opcode=%d", opcode); + J2dTraceLn(J2D_TRACE_VERBOSE, "D3DRQ_flushBuffer: opcode=%d", opcode); switch (opcode) { @@ -839,8 +839,8 @@ void D3DRQ_FlushBuffer(void *pParam) break; default: - J2dRlsTraceLn1(J2D_TRACE_ERROR, - "D3DRQ_flushBuffer: invalid opcode=%d", opcode); + J2dRlsTraceLn(J2D_TRACE_ERROR, + "D3DRQ_flushBuffer: invalid opcode=%d", opcode); return; } // we may mark the surface lost repeatedly but that won't do much harm diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DRenderer.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DRenderer.cpp index 384559d90fd..32126ddc2f5 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DRenderer.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DRenderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,9 +35,9 @@ HRESULT D3DRenderer_DrawLine(D3DContext *d3dc, jint x1, jint y1, jint x2, jint y2) { - J2dTraceLn4(J2D_TRACE_INFO, - "D3DRenderer_doDrawLineD3D x1=%-4d y1=%-4d x2=%-4d y2=%-4d", - x1, y1, x2, y2); + J2dTraceLn(J2D_TRACE_INFO, + "D3DRenderer_doDrawLineD3D x1=%-4d y1=%-4d x2=%-4d y2=%-4d", + x1, y1, x2, y2); d3dc->BeginScene(STATE_RENDEROP); return d3dc->pVCacher->DrawLine(x1, y1, x2, y2); } @@ -46,9 +46,9 @@ HRESULT D3DRenderer_DrawRect(D3DContext *d3dc, jint x, jint y, jint w, jint h) { - J2dTraceLn4(J2D_TRACE_INFO, - "D3DRenderer_DrawRect x=%-4d y=%-4d w=%-4d h=%-4d", - x, y, w, h); + J2dTraceLn(J2D_TRACE_INFO, + "D3DRenderer_DrawRect x=%-4d y=%-4d w=%-4d h=%-4d", + x, y, w, h); d3dc->BeginScene(STATE_RENDEROP); return d3dc->pVCacher->DrawRect(x, y, x + w, y + h); @@ -58,9 +58,9 @@ HRESULT D3DRenderer_FillRect(D3DContext *d3dc, jint x, jint y, jint w, jint h) { - J2dTraceLn4(J2D_TRACE_INFO, + J2dTraceLn(J2D_TRACE_INFO, "D3DRenderer_FillRect x=%-4d y=%-4d w=%-4d h=%-4d", - x, y, w, h); + x, y, w, h); d3dc->BeginScene(STATE_RENDEROP); return d3dc->pVCacher->FillRect(x, y, x + w, y + h); @@ -120,14 +120,14 @@ D3DRenderer_FillParallelogram(D3DContext *d3dc, jfloat dx21, jfloat dy21, jfloat dx12, jfloat dy12) { - J2dTraceLn6(J2D_TRACE_INFO, - "D3DRenderer_FillParallelogram " - "x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f " - "dx2=%6.2f dy2=%6.2f ", - fx11, fy11, - dx21, dy21, - dx12, dy12); + J2dTraceLn(J2D_TRACE_INFO, + "D3DRenderer_FillParallelogram " + "x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f " + "dx2=%6.2f dy2=%6.2f ", + fx11, fy11, + dx21, dy21, + dx12, dy12); d3dc->BeginScene(STATE_RENDEROP); return d3dc->pVCacher->FillParallelogram(fx11, fy11, @@ -144,14 +144,14 @@ D3DRenderer_DrawParallelogram(D3DContext *d3dc, { HRESULT res; - J2dTraceLn8(J2D_TRACE_INFO, - "D3DRenderer_DrawParallelogram " - "x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " - "dx2=%6.2f dy2=%6.2f lwr2=%6.2f ", - fx11, fy11, - dx21, dy21, lwr21, - dx12, dy12, lwr12); + J2dTraceLn(J2D_TRACE_INFO, + "D3DRenderer_DrawParallelogram " + "x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " + "dx2=%6.2f dy2=%6.2f lwr2=%6.2f ", + fx11, fy11, + dx21, dy21, lwr21, + dx12, dy12, lwr12); // dx,dy for line width in the "21" and "12" directions. jfloat ldx21 = dx21 * lwr21; @@ -251,14 +251,14 @@ D3DRenderer_FillAAParallelogram(D3DContext *d3dc, IDirect3DDevice9 *pd3dDevice; HRESULT res; - J2dTraceLn6(J2D_TRACE_INFO, - "D3DRenderer_FillAAParallelogram " - "x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f " - "dx2=%6.2f dy2=%6.2f ", - fx11, fy11, - dx21, dy21, - dx12, dy12); + J2dTraceLn(J2D_TRACE_INFO, + "D3DRenderer_FillAAParallelogram " + "x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f " + "dx2=%6.2f dy2=%6.2f ", + fx11, fy11, + dx21, dy21, + dx12, dy12); res = d3dc->BeginScene(STATE_AAPGRAMOP); RETURN_STATUS_IF_FAILED(res); @@ -290,14 +290,14 @@ D3DRenderer_DrawAAParallelogram(D3DContext *d3dc, jfloat ifx11, ify11, idx21, idy21, idx12, idy12; HRESULT res; - J2dTraceLn8(J2D_TRACE_INFO, - "D3DRenderer_DrawAAParallelogram " - "x=%6.2f y=%6.2f " - "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " - "dx2=%6.2f dy2=%6.2f lwr2=%6.2f ", - fx11, fy11, - dx21, dy21, lwr21, - dx12, dy12, lwr12); + J2dTraceLn(J2D_TRACE_INFO, + "D3DRenderer_DrawAAParallelogram " + "x=%6.2f y=%6.2f " + "dx1=%6.2f dy1=%6.2f lwr1=%6.2f " + "dx2=%6.2f dy2=%6.2f lwr2=%6.2f ", + fx11, fy11, + dx21, dy21, lwr21, + dx12, dy12, lwr12); res = d3dc->BeginScene(STATE_AAPGRAMOP); RETURN_STATUS_IF_FAILED(res); diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DResourceManager.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DResourceManager.cpp index 2841cf82fd6..4d2826507d3 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DResourceManager.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DResourceManager.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ D3DResource::Init(IDirect3DResource9 *pRes, IDirect3DSwapChain9 *pSC) ((IDirect3DCubeTexture9*)pResource)->GetLevelDesc(0, &desc); break; default: - J2dTraceLn1(J2D_TRACE_VERBOSE, " resource type=%d", type); + J2dTraceLn(J2D_TRACE_VERBOSE, " resource type=%d", type); } } else if (pSwapChain != NULL) { pSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pSurface); @@ -90,9 +90,9 @@ D3DResource::SetSDOps(D3DSDOps *pOps) if (pOps != NULL && this->pOps != NULL) { // something's wrong, we're overwriting // a non-null field (setting it to null is allowed) - J2dTraceLn2(J2D_TRACE_WARNING, - "D3DResource::SetSDOps: overwriting "\ - "this->pOps=0x%x with pOps=0x%x", this->pOps, pOps); + J2dTraceLn(J2D_TRACE_WARNING, + "D3DResource::SetSDOps: overwriting "\ + "this->pOps=0x%x with pOps=0x%x", this->pOps, pOps); } this->pOps = pOps; } @@ -157,7 +157,7 @@ D3DResourceManager::D3DResourceManager() HRESULT D3DResourceManager::Init(D3DContext *pCtx) { - J2dTraceLn1(J2D_TRACE_INFO, "D3DRM::Init pCtx=%x", pCtx); + J2dTraceLn(J2D_TRACE_INFO, "D3DRM::Init pCtx=%x", pCtx); if (this->pCtx != pCtx || (this->pCtx != NULL && this->pCtx->Get3DDevice() != pCtx->Get3DDevice())) @@ -211,7 +211,7 @@ D3DResourceManager::ReleaseResource(IManagedResource* pResource) J2dTraceLn(J2D_TRACE_INFO, "D3DRM::ReleaseResource"); if (pResource != NULL) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " releasing pResource=%x", pResource); + J2dTraceLn(J2D_TRACE_VERBOSE, " releasing pResource=%x", pResource); if (pResource->pPrev != NULL) { pResource->pPrev->pNext = pResource->pNext; } else { @@ -237,7 +237,7 @@ D3DResourceManager::AddResource(IManagedResource* pResource) J2dTraceLn(J2D_TRACE_INFO, "D3DRM::AddResource"); if (pResource != NULL) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " pResource=%x", pResource); + J2dTraceLn(J2D_TRACE_VERBOSE, " pResource=%x", pResource); pResource->pPrev = NULL; pResource->pNext = pHead; if (pHead != NULL) { @@ -261,8 +261,8 @@ D3DResourceManager::CreateTexture(UINT width, UINT height, IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateTexture"); - J2dTraceLn4(J2D_TRACE_VERBOSE, " w=%d h=%d isRTT=%d isOpaque=%d", - width, height, isRTT, isOpaque); + J2dTraceLn(J2D_TRACE_VERBOSE, " w=%d h=%d isRTT=%d isOpaque=%d", + width, height, isRTT, isOpaque); if (ppTextureResource == NULL || pCtx == NULL || (pd3dDevice = pCtx->Get3DDevice()) == NULL) @@ -317,7 +317,7 @@ D3DResourceManager::CreateTexture(UINT width, UINT height, res = pd3dDevice->CreateTexture(width, height, 1/*levels*/, dwUsage, format, pool, &pTexture, 0); if (SUCCEEDED(res)) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " created texture: 0x%x", pTexture); + J2dTraceLn(J2D_TRACE_VERBOSE, " created texture: 0x%x", pTexture); *ppTextureResource = new D3DResource((IDirect3DResource9*)pTexture); res = AddResource(*ppTextureResource); } else { @@ -342,8 +342,8 @@ HRESULT D3DResourceManager::CreateRTSurface(UINT width, UINT height, IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateRTSurface"); - J2dTraceLn3(J2D_TRACE_VERBOSE, " w=%d h=%d isOpaque=%d", - width, height, isOpaque); + J2dTraceLn(J2D_TRACE_VERBOSE, " w=%d h=%d isOpaque=%d", + width, height, isOpaque); if (pCtx == NULL || ppSurfaceResource == NULL || (pd3dDevice = pCtx->Get3DDevice()) == NULL) @@ -363,7 +363,7 @@ HRESULT D3DResourceManager::CreateRTSurface(UINT width, UINT height, isLockable, &pSurface, NULL); if (SUCCEEDED(res)) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " created RT Surface: 0x%x ", pSurface); + J2dTraceLn(J2D_TRACE_VERBOSE, " created RT Surface: 0x%x ", pSurface); if (pFormat != NULL) { *pFormat = format; } @@ -385,7 +385,7 @@ HRESULT D3DResourceManager::CreateOSPSurface(UINT width, UINT height, IDirect3DDevice9 *pd3dDevice; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateOSPSurface"); - J2dTraceLn2(J2D_TRACE_VERBOSE, " w=%d h=%d", width, height); + J2dTraceLn(J2D_TRACE_VERBOSE, " w=%d h=%d", width, height); if (pCtx == NULL || ppSurfaceResource == NULL || (pd3dDevice = pCtx->Get3DDevice()) == NULL) @@ -413,7 +413,7 @@ HRESULT D3DResourceManager::CreateOSPSurface(UINT width, UINT height, format, pool, &pSurface, NULL); if (SUCCEEDED(res)) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " created OSP Surface: 0x%x ",pSurface); + J2dTraceLn(J2D_TRACE_VERBOSE, " created OSP Surface: 0x%x ",pSurface); *ppSurfaceResource = new D3DResource((IDirect3DResource9*)pSurface); res = AddResource(*ppSurfaceResource); } else { @@ -436,8 +436,8 @@ D3DResourceManager::CreateSwapChain(HWND hWnd, UINT numBuffers, D3DPRESENT_PARAMETERS newParams, *curParams; J2dTraceLn(J2D_TRACE_INFO, "D3DRM::CreateSwapChain"); - J2dTraceLn4(J2D_TRACE_VERBOSE, " w=%d h=%d hwnd=%x numBuffers=%d", - width, height, hWnd, numBuffers); + J2dTraceLn(J2D_TRACE_VERBOSE, " w=%d h=%d hwnd=%x numBuffers=%d", + width, height, hWnd, numBuffers); if (pCtx == NULL || ppSwapChainResource == NULL || (pd3dDevice = pCtx->Get3DDevice()) == NULL) @@ -481,7 +481,7 @@ D3DResourceManager::CreateSwapChain(HWND hWnd, UINT numBuffers, } if (SUCCEEDED(res)) { - J2dTraceLn1(J2D_TRACE_VERBOSE," created swap chain: 0x%x ",pSwapChain); + J2dTraceLn(J2D_TRACE_VERBOSE," created swap chain: 0x%x ",pSwapChain); *ppSwapChainResource = new D3DResource(pSwapChain); res = AddResource(*ppSwapChainResource); } else { diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DShaderGen.c b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DShaderGen.c index 51c9b37801e..14de44a85f2 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DShaderGen.c +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DShaderGen.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,10 +55,8 @@ static char *strHeaderFile = "D3DShaders.h"; (((flags) & (flagbit)) != 0) // REMIND -//#define J2dTraceLn(a, b) fprintf(stderr, "%s\n", b); -//#define J2dTraceLn1(a, b, c) fprintf(stderr, b, c); -#define J2dTraceLn(a, b) -#define J2dTraceLn1(a, b, c) +//#define J2dTraceLn(level, ...) (fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n")); +#define J2dTraceLn(level, ...) /************************* General shader support ***************************/ @@ -212,9 +210,9 @@ D3DShaderGen_GenerateConvolveShader(int flags) char *edge; char finalSource[2000]; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DShaderGen_GenerateConvolveShader: flags=%d", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "D3DShaderGen_GenerateConvolveShader: flags=%d", + flags); if (IS_SET(CONVOLVE_EDGE_ZERO_FILL)) { // EDGE_ZERO_FILL: fill in zero at the edges @@ -273,9 +271,9 @@ D3DShaderGen_GenerateRescaleShader(int flags) char *postRescale = ""; char finalSource[2000]; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DShaderGen_GenerateRescaleShader: flags=%d", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "D3DShaderGen_GenerateRescaleShader: flags=%d", + flags); if (IS_SET(RESCALE_NON_PREMULT)) { preRescale = "srcColor.rgb /= srcColor.a;"; @@ -338,9 +336,9 @@ D3DShaderGen_GenerateLookupShader(int flags) char *postLookup = ""; char finalSource[2000]; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DShaderGen_GenerateLookupShader: flags=%d", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "D3DShaderGen_GenerateLookupShader: flags=%d", + flags); if (IS_SET(LOOKUP_USE_SRC_ALPHA)) { // when numComps is 1 or 3, the alpha is not looked up in the table; @@ -427,9 +425,9 @@ D3DShaderGen_GenerateBasicGradShader(int flags) char *maskCode = ""; char finalSource[3000]; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DShaderGen_GenerateBasicGradShader", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "D3DShaderGen_GenerateBasicGradShader", + flags); if (IS_SET(BASIC_GRAD_IS_CYCLIC)) { cycleCode = @@ -689,9 +687,9 @@ D3DShaderGen_GenerateLinearGradShader(int flags) char *paintVars; char *distCode; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DShaderGen_GenerateLinearGradShader", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "D3DShaderGen_GenerateLinearGradShader", + flags); /* * To simplify the code and to make it easier to upload a number of @@ -720,9 +718,9 @@ D3DShaderGen_GenerateRadialGradShader(int flags) char *paintVars; char *distCode; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DShaderGen_GenerateRadialGradShader", - flags); + J2dTraceLn(J2D_TRACE_INFO, + "D3DShaderGen_GenerateRadialGradShader", + flags); /* * To simplify the code and to make it easier to upload a number of diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DSurfaceData.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DSurfaceData.cpp index 38d9e1ecc58..9527760033c 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DSurfaceData.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DSurfaceData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -248,8 +248,8 @@ JNICALL Java_sun_java2d_d3d_D3DSurfaceData_initTexture isRTT, isOpaque, &format, 0/*usage*/, &d3dsdo->pResource); if (SUCCEEDED(res)) { - J2dTraceLn1(J2D_TRACE_VERBOSE, - " created texture pResource=%x", d3dsdo->pResource); + J2dTraceLn(J2D_TRACE_VERBOSE, + " created texture pResource=%x", d3dsdo->pResource); d3dsdo->pResource->SetSDOps(d3dsdo); } else { D3DRQ_MarkLostIfNeeded(res, d3dsdo); @@ -293,8 +293,8 @@ Java_sun_java2d_d3d_D3DSurfaceData_initRTSurface isOpaque, FALSE /*lockable*/, &format, &d3dsdo->pResource); if (SUCCEEDED(res)) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " created RT surface pResource=0x%x", - d3dsdo->pResource); + J2dTraceLn(J2D_TRACE_VERBOSE, " created RT surface pResource=0x%x", + d3dsdo->pResource); d3dsdo->pResource->SetSDOps(d3dsdo); } else { D3DRQ_MarkLostIfNeeded(res, d3dsdo); @@ -390,8 +390,8 @@ JNICALL Java_sun_java2d_d3d_D3DSurfaceData_initFlipBackbuffer d3dsdo->swapEffect, presentationInterval, &d3dsdo->pResource); if (SUCCEEDED(res)) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " created swap chain pResource=0x%x", - d3dsdo->pResource); + J2dTraceLn(J2D_TRACE_VERBOSE, " created swap chain pResource=0x%x", + d3dsdo->pResource); d3dsdo->pResource->SetSDOps(d3dsdo); } else { D3DRQ_MarkLostIfNeeded(res, d3dsdo); @@ -531,7 +531,7 @@ JNIEXPORT jlong JNICALL { D3DSDOps *d3dsdo; - J2dTraceLn(J2D_TRACE_INFO, "D3DSurfaceData_getNativeResourceNative") + J2dTraceLn(J2D_TRACE_INFO, "D3DSurfaceData_getNativeResourceNative"); RETURN_STATUS_IF_NULL(d3dsdo = (D3DSDOps *)jlong_to_ptr(pData), 0L); diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DTextRenderer.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DTextRenderer.cpp index c86e2f14a40..c8ed19914fb 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DTextRenderer.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DTextRenderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,8 +133,8 @@ D3DTR_UpdateLCDTextColor(D3DContext *d3dc, jint contrast) jfloat gamma = ((jfloat)contrast) / 100.0f; jfloat clr[4]; - J2dTraceLn1(J2D_TRACE_INFO, - "D3DTR_UpdateLCDTextColor: contrast=%d", contrast); + J2dTraceLn(J2D_TRACE_INFO, + "D3DTR_UpdateLCDTextColor: contrast=%d", contrast); /* * Note: Ideally we would update the "srcAdj" uniform parameter only diff --git a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DVertexCacher.cpp b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DVertexCacher.cpp index 4f108001b87..300ffd73bed 100644 --- a/src/java.desktop/windows/native/libawt/java2d/d3d/D3DVertexCacher.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/d3d/D3DVertexCacher.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -733,11 +733,11 @@ HRESULT D3DVertexCacher::Render(int actionType) res = lpD3DVertexBuffer->Unlock(); UINT currentVertex = firstPendingVertex; UINT batchSize; - J2dTraceLn2(J2D_TRACE_VERBOSE, - "D3DVC::Render Starting flushing of %d vertices "\ - "in %d batches", - pendingVertices, - (currentBatch - firstPendingBatch + 1)); + J2dTraceLn(J2D_TRACE_VERBOSE, + "D3DVC::Render Starting flushing of %d vertices "\ + "in %d batches", + pendingVertices, + (currentBatch - firstPendingBatch + 1)); for (UINT b = firstPendingBatch; b <= currentBatch; b++) { @@ -785,20 +785,20 @@ HRESULT D3DVertexCacher::EnsureCapacity(D3DPRIMITIVETYPE newPType, UINT vNum) // if we can't fit new vertices in the vertex buffer, // render whatever we have in the buffer and start // from the beginning of the vertex buffer - J2dTraceLn2(J2D_TRACE_VERBOSE, - "D3DVC::EnsureCapacity exceeded capacity. "\ - "current v: %d, requested vertices: %d\n", - firstUnusedVertex, vNum); + J2dTraceLn(J2D_TRACE_VERBOSE, + "D3DVC::EnsureCapacity exceeded capacity. "\ + "current v: %d, requested vertices: %d\n", + firstUnusedVertex, vNum); if (FAILED(res = Render(RESET_ACTION))) { return res; } } - J2dTraceLn5(J2D_TRACE_VERBOSE, - "D3DVC::EnsureCapacity current batch: %d "\ - " batch.type=%d newType=%d vNum=%d firstUnusedV=%d", - currentBatch, batches[currentBatch].pType, newPType, vNum, - firstUnusedVertex); + J2dTraceLn(J2D_TRACE_VERBOSE, + "D3DVC::EnsureCapacity current batch: %d "\ + " batch.type=%d newType=%d vNum=%d firstUnusedV=%d", + currentBatch, batches[currentBatch].pType, newPType, vNum, + firstUnusedVertex); // there should not be multiple linestrips in a batch, // or they will be counted as a single line strip if (batches[currentBatch].pType != newPType || diff --git a/src/java.desktop/windows/native/libawt/java2d/opengl/WGLGraphicsConfig.c b/src/java.desktop/windows/native/libawt/java2d/opengl/WGLGraphicsConfig.c index 0b495738a5a..7f69093388b 100644 --- a/src/java.desktop/windows/native/libawt/java2d/opengl/WGLGraphicsConfig.c +++ b/src/java.desktop/windows/native/libawt/java2d/opengl/WGLGraphicsConfig.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,9 +245,9 @@ WGLGC_GetPixelFormatForDC(HDC hdc) db = attrVals[2]; alpha = attrVals[3]; - J2dRlsTrace5(J2D_TRACE_VERBOSE, - "[V] pixfmt=%d db=%d alpha=%d depth=%d stencil=%d valid=", - pixfmt, db, alpha, depth, stencil); + J2dRlsTrace(J2D_TRACE_VERBOSE, "[V] "\ + "pixfmt=%d db=%d alpha=%d depth=%d stencil=%d valid=", + pixfmt, db, alpha, depth, stencil); if ((depth + stencil) < minDepthPlusStencil) { J2dRlsTrace(J2D_TRACE_VERBOSE, "true\n"); @@ -264,9 +264,8 @@ WGLGC_GetPixelFormatForDC(HDC hdc) return 0; } - J2dRlsTraceLn1(J2D_TRACE_INFO, - "WGLGC_GetPixelFormatForDC: chose %d as the best pixel format", - chosenPixFmt); + J2dRlsTraceLn(J2D_TRACE_INFO, "WGLGC_GetPixelFormatForDC: "\ + "chose %d as the best pixel format", chosenPixFmt); return chosenPixFmt; } @@ -595,9 +594,9 @@ Java_sun_java2d_opengl_WGLGraphicsConfig_getWGLConfigInfo(JNIEnv *env, extstr = j2d_wglGetExtensionsStringARB(hdc); OGLContext_GetExtensionInfo(env, &caps); - J2dRlsTraceLn1(J2D_TRACE_INFO, - "WGLGraphicsConfig_getWGLConfigInfo: OpenGL version=%s", - (versionstr == NULL) ? "null" : (char *)versionstr); + J2dRlsTraceLn(J2D_TRACE_INFO, + "WGLGraphicsConfig_getWGLConfigInfo: OpenGL version=%s", + (versionstr == NULL) ? "null" : (char *)versionstr); if (!OGLContext_IsVersionSupported(versionstr)) { J2dRlsTraceLn(J2D_TRACE_ERROR, diff --git a/src/java.desktop/windows/native/libawt/java2d/opengl/WGLSurfaceData.c b/src/java.desktop/windows/native/libawt/java2d/opengl/WGLSurfaceData.c index 76bbb89c526..c83e42a4d40 100644 --- a/src/java.desktop/windows/native/libawt/java2d/opengl/WGLSurfaceData.c +++ b/src/java.desktop/windows/native/libawt/java2d/opengl/WGLSurfaceData.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -212,9 +212,9 @@ OGLSD_MakeOGLContextCurrent(JNIEnv *env, OGLSDOps *srcOps, OGLSDOps *dstOps) J2dTraceLn(J2D_TRACE_INFO, "OGLSD_MakeOGLContextCurrent"); - J2dTraceLn4(J2D_TRACE_VERBOSE, " src: %d %p dst: %d %p", - srcOps->drawableType, srcOps, - dstOps->drawableType, dstOps); + J2dTraceLn(J2D_TRACE_VERBOSE, " src: %d %p dst: %d %p", + srcOps->drawableType, srcOps, + dstOps->drawableType, dstOps); oglc = dstWGLOps->configInfo->context; if (oglc == NULL) { @@ -354,8 +354,8 @@ OGLSD_InitOGLWindow(JNIEnv *env, OGLSDOps *oglsdo) oglsdo->height = wbounds.bottom - wbounds.top; wglsdo->pbufferDC = 0; - J2dTraceLn2(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", - oglsdo->width, oglsdo->height); + J2dTraceLn(J2D_TRACE_VERBOSE, " created window: w=%d h=%d", + oglsdo->width, oglsdo->height); return JNI_TRUE; } diff --git a/src/java.desktop/windows/native/libawt/java2d/windows/GDIRenderer.cpp b/src/java.desktop/windows/native/libawt/java2d/windows/GDIRenderer.cpp index bea2b07e08f..18dfe01ff33 100644 --- a/src/java.desktop/windows/native/libawt/java2d/windows/GDIRenderer.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/windows/GDIRenderer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -132,9 +132,9 @@ Java_sun_java2d_windows_GDIRenderer_doDrawLine jint x1, jint y1, jint x2, jint y2) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawLine"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x x1=%-4d y1=%-4d x2=%-4d y2=%-4d", - color, x1, y1, x2, y2); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x x1=%-4d y1=%-4d x2=%-4d y2=%-4d", + color, x1, y1, x2, y2); GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData); if (wsdo == NULL) { return; @@ -179,9 +179,9 @@ Java_sun_java2d_windows_GDIRenderer_doDrawRect jint x, jint y, jint w, jint h) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawRect"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", - color, x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", + color, x, y, w, h); if (w < 0 || h < 0) { return; } @@ -224,11 +224,11 @@ Java_sun_java2d_windows_GDIRenderer_doDrawRoundRect jint x, jint y, jint w, jint h, jint arcW, jint arcH) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawRoundRect"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", - color, x, y, w, h); - J2dTraceLn2(J2D_TRACE_VERBOSE, " arcW=%-4d arcH=%-4d", - arcW, arcH); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", + color, x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, " arcW=%-4d arcH=%-4d", + arcW, arcH); if (w < 2 || h < 2 || arcW <= 0 || arcH <= 0) { // Fix for 4524760 - drawRoundRect0 test case fails on Windows 98 // Thin round rects degenerate into regular rectangles @@ -268,9 +268,9 @@ Java_sun_java2d_windows_GDIRenderer_doDrawOval jint x, jint y, jint w, jint h) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawOval"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", - color, x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", + color, x, y, w, h); if (w < 2 || h < 2) { // Thin enough ovals have no room for curvature. Defer to // the DrawRect method which handles degenerate sizes better. @@ -307,12 +307,12 @@ Java_sun_java2d_windows_GDIRenderer_doDrawArc jint angleStart, jint angleExtent) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawArc"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", - color, x, y, w, h); - J2dTraceLn2(J2D_TRACE_VERBOSE, - " angleStart=%-4d angleExtent=%-4d", - angleStart, angleExtent); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", + color, x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, + " angleStart=%-4d angleExtent=%-4d", + angleStart, angleExtent); if (w < 0 || h < 0 || angleExtent == 0) { return; } @@ -364,10 +364,10 @@ Java_sun_java2d_windows_GDIRenderer_doDrawPoly jint npoints, jboolean isclosed) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doDrawPoly"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x transx=%-4d transy=%-4d "\ - "npoints=%-4d isclosed=%-4d", - color, transx, transy, npoints, isclosed); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x transx=%-4d transy=%-4d "\ + "npoints=%-4d isclosed=%-4d", + color, transx, transy, npoints, isclosed); if (JNU_IsNull(env, xpointsarray) || JNU_IsNull(env, ypointsarray)) { JNU_ThrowNullPointerException(env, "coordinate array"); return; @@ -434,9 +434,9 @@ Java_sun_java2d_windows_GDIRenderer_doFillRect jint x, jint y, jint w, jint h) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillRect"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", - color, x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", + color, x, y, w, h); if (w <= 0 || h <= 0) { return; } @@ -467,11 +467,11 @@ Java_sun_java2d_windows_GDIRenderer_doFillRoundRect jint x, jint y, jint w, jint h, jint arcW, jint arcH) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillRoundRect"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", - color, x, y, w, h); - J2dTraceLn2(J2D_TRACE_VERBOSE, " arcW=%-4d arcH=%-4d", - arcW, arcH); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", + color, x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, " arcW=%-4d arcH=%-4d", + arcW, arcH); if (w < 2 || h < 2 || arcW <= 0 || arcH <= 0) { // Fix related to 4524760 - drawRoundRect0 fails on Windows 98 // Thin round rects have no room for curvature. Also, if @@ -510,9 +510,9 @@ Java_sun_java2d_windows_GDIRenderer_doFillOval jint x, jint y, jint w, jint h) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillOval"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", - color, x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", + color, x, y, w, h); if (w < 3 || h < 3) { // Fix for 4411814 - small ovals do not draw anything // (related to 4205762 on Solaris platform) @@ -578,12 +578,12 @@ Java_sun_java2d_windows_GDIRenderer_doFillArc jint angleStart, jint angleExtent) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillArc"); - J2dTraceLn5(J2D_TRACE_VERBOSE, - " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", - color, x, y, w, h); - J2dTraceLn2(J2D_TRACE_VERBOSE, - " angleStart=%-4d angleExtent=%-4d", - angleStart, angleExtent); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x x=%-4d y=%-4d w=%-4d h=%-4d", + color, x, y, w, h); + J2dTraceLn(J2D_TRACE_VERBOSE, + " angleStart=%-4d angleExtent=%-4d", + angleStart, angleExtent); if (w <= 0 || h <= 0 || angleExtent == 0) { return; } @@ -639,9 +639,9 @@ Java_sun_java2d_windows_GDIRenderer_doFillPoly jint npoints) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doFillPoly"); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " color=0x%x transx=%-4d transy=%-4d npoints=%-4d", - color, transx, transy, npoints); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x transx=%-4d transy=%-4d npoints=%-4d", + color, transx, transy, npoints); if (JNU_IsNull(env, xpointsarray) || JNU_IsNull(env, ypointsarray)) { JNU_ThrowNullPointerException(env, "coordinate array"); return; @@ -710,9 +710,9 @@ Java_sun_java2d_windows_GDIRenderer_doShape jobject p2df, jboolean isfill) { J2dTraceLn(J2D_TRACE_INFO, "GDIRenderer_doShape"); - J2dTraceLn4(J2D_TRACE_VERBOSE, - " color=0x%x transx=%-4d transy=%-4d isfill=%-4d", - color, transX, transY, isfill); + J2dTraceLn(J2D_TRACE_VERBOSE, + " color=0x%x transx=%-4d transy=%-4d isfill=%-4d", + color, transX, transY, isfill); GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, sData); if (wsdo == NULL) { return; @@ -892,9 +892,9 @@ Java_sun_java2d_windows_GDIRenderer_devCopyArea { GDIWinSDOps *wsdo = GDIWindowSurfaceData_GetOps(env, wsd); J2dTraceLn(J2D_TRACE_INFO, "GDIWindowSurfaceData_devCopyArea"); - J2dTraceLn4(J2D_TRACE_VERBOSE, " srcx=%-4d srcy=%-4d dx=%-4d dy=%-4d", - srcx, srcy, dx, dy); - J2dTraceLn2(J2D_TRACE_VERBOSE, " w=%-4d h=%-4d", width, height); + J2dTraceLn(J2D_TRACE_VERBOSE, " srcx=%-4d srcy=%-4d dx=%-4d dy=%-4d", + srcx, srcy, dx, dy); + J2dTraceLn(J2D_TRACE_VERBOSE, " w=%-4d h=%-4d", width, height); if (wsdo == NULL) { return; } diff --git a/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp b/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp index 406a82a022f..004637737d3 100644 --- a/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/windows/GDIWindowSurfaceData.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,9 +76,9 @@ void SetupThreadGraphicsInfo(JNIEnv *env, GDIWinSDOps *wsdo) { info = new ThreadGraphicsInfo; ZeroMemory(info, sizeof(ThreadGraphicsInfo)); TlsSetValue(threadInfoIndex, (LPVOID)info); - J2dTraceLn2(J2D_TRACE_VERBOSE, - " current batch limit for thread 0x%x is %d", - GetCurrentThreadId(), ::GdiGetBatchLimit()); + J2dTraceLn(J2D_TRACE_VERBOSE, + " current batch limit for thread 0x%x is %d", + GetCurrentThreadId(), ::GdiGetBatchLimit()); J2dTraceLn(J2D_TRACE_VERBOSE, " setting to the limit to 1"); // Fix for bug 4374079 ::GdiSetBatchLimit(1); @@ -403,8 +403,8 @@ Java_sun_java2d_windows_GDIWindowSurfaceData_initOps(JNIEnv *env, jobject wsd, // GDIWindowSurfaceData_GetWindow will throw NullPointerException // if wsdo->window is NULL wsdo->window = GDIWindowSurfaceData_GetWindow(env, wsdo); - J2dTraceLn2(J2D_TRACE_VERBOSE, " wsdo=0x%x wsdo->window=0x%x", - wsdo, wsdo->window); + J2dTraceLn(J2D_TRACE_VERBOSE, " wsdo=0x%x wsdo->window=0x%x", + wsdo, wsdo->window); { Devices::InstanceAccess devices; @@ -414,15 +414,15 @@ Java_sun_java2d_windows_GDIWindowSurfaceData_initOps(JNIEnv *env, jobject wsd, !SurfaceDepthsCompatible(depth, wsdo->device->GetBitDepth())) { if (wsdo->device != NULL) { - J2dTraceLn2(J2D_TRACE_WARNING, - "GDIWindowSurfaceData_initOps: Surface depth mismatch: "\ - "wsdo->depth=%d device depth=%d. Surface invalidated.", - wsdo->depth, wsdo->device->GetBitDepth()); + J2dTraceLn(J2D_TRACE_WARNING, + "GDIWindowSurfaceData_initOps: Surface depth mismatch: "\ + "wsdo->depth=%d device depth=%d. Surface invalidated.", + wsdo->depth, wsdo->device->GetBitDepth()); } else { - J2dTraceLn1(J2D_TRACE_WARNING, - "GDIWindowSurfaceData_initOps: Incorrect "\ - "screen number (screen=%d). Surface invalidated.", - screen); + J2dTraceLn(J2D_TRACE_WARNING, + "GDIWindowSurfaceData_initOps: Incorrect "\ + "screen number (screen=%d). Surface invalidated.", + screen); } wsdo->invalid = JNI_TRUE; @@ -461,9 +461,9 @@ GDIWindowSurfaceData_GetComp(JNIEnv *env, GDIWinSDOps *wsdo) jobject localObj = env->NewLocalRef(wsdo->peer); if (localObj == NULL || (pData = JNI_GET_PDATA(localObj)) == NULL) { - J2dTraceLn1(J2D_TRACE_WARNING, - "GDIWindowSurfaceData_GetComp: Null pData? pData=0x%x", - pData); + J2dTraceLn(J2D_TRACE_WARNING, + "GDIWindowSurfaceData_GetComp: Null pData? pData=0x%x", + pData); if (beingShutdown == JNI_TRUE) { wsdo->invalid = JNI_TRUE; return (AwtComponent *) NULL; @@ -1057,8 +1057,8 @@ static void GDIWinSD_ReleaseDC(JNIEnv *env, GDIWinSDOps *wsdo, HDC hDC) static void GDIWinSD_InvalidateSD(JNIEnv *env, GDIWinSDOps *wsdo) { J2dTraceLn(J2D_TRACE_INFO, "GDIWinSD_InvalidateSD"); - J2dTraceLn2(J2D_TRACE_VERBOSE, " wsdo=0x%x wsdo->window=0x%x", - wsdo, wsdo->window); + J2dTraceLn(J2D_TRACE_VERBOSE, " wsdo=0x%x wsdo->window=0x%x", + wsdo, wsdo->window); wsdo->invalid = JNI_TRUE; } diff --git a/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.cpp b/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.cpp index 9ed0f38bd10..189525c39a1 100644 --- a/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.cpp +++ b/src/java.desktop/windows/native/libawt/java2d/windows/WindowsFlags.cpp @@ -93,12 +93,12 @@ void GetFlagValues(JNIEnv *env, jclass wFlagsClass) JNU_CHECK_EXCEPTION(env); J2dTraceLn(J2D_TRACE_INFO, "WindowsFlags (native):"); - J2dTraceLn1(J2D_TRACE_INFO, " d3dEnabled = %s", - (useD3D ? "true" : "false")); - J2dTraceLn1(J2D_TRACE_INFO, " d3dSet = %s", - (forceD3DUsage ? "true" : "false")); - J2dTraceLn1(J2D_TRACE_INFO, " setHighDPIAware = %s", - (setHighDPIAware ? "true" : "false")); + J2dTraceLn(J2D_TRACE_INFO, " d3dEnabled = %s", + (useD3D ? "true" : "false")); + J2dTraceLn(J2D_TRACE_INFO, " d3dSet = %s", + (forceD3DUsage ? "true" : "false")); + J2dTraceLn(J2D_TRACE_INFO, " setHighDPIAware = %s", + (setHighDPIAware ? "true" : "false")); } void SetD3DEnabledFlag(JNIEnv *env, BOOL d3dEnabled, BOOL d3dSet) diff --git a/src/java.desktop/windows/native/libawt/windows/Devices.cpp b/src/java.desktop/windows/native/libawt/windows/Devices.cpp index e275cb77a57..8096b1084a2 100644 --- a/src/java.desktop/windows/native/libawt/windows/Devices.cpp +++ b/src/java.desktop/windows/native/libawt/windows/Devices.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -99,13 +99,17 @@ static BOOL IsValidMonitor(HMONITOR hMon) memset((void*)(&mieInfo), 0, sizeof(MONITORINFOEX)); mieInfo.cbSize = sizeof(MONITORINFOEX); if (!::GetMonitorInfo(hMon, (LPMONITORINFOEX)(&mieInfo))) { - J2dTraceLn1(J2D_TRACE_INFO, "Devices::IsValidMonitor: GetMonitorInfo failed for monitor with handle %p", hMon); + J2dTraceLn(J2D_TRACE_INFO, + "Devices::IsValidMonitor: GetMonitorInfo failed for monitor with handle %p", + hMon); return FALSE; } HDC hDC = CreateDC(mieInfo.szDevice, NULL, NULL, NULL); if (NULL == hDC) { - J2dTraceLn2(J2D_TRACE_INFO, "Devices::IsValidMonitor: CreateDC failed for monitor with handle %p, device: %S", hMon, mieInfo.szDevice); + J2dTraceLn(J2D_TRACE_INFO, + "Devices::IsValidMonitor: CreateDC failed for monitor with handle %p, device: %S", + hMon, mieInfo.szDevice); return FALSE; } @@ -183,7 +187,7 @@ CriticalSection Devices::arrayLock; */ Devices::Devices(int numDevices) { - J2dTraceLn1(J2D_TRACE_INFO, "Devices::Devices numDevices=%d", numDevices); + J2dTraceLn(J2D_TRACE_INFO, "Devices::Devices numDevices=%d", numDevices); this->numDevices = numDevices; this->refCount = 0; devices = (AwtWin32GraphicsDevice**)SAFE_SIZE_ARRAY_ALLOC(safe_Malloc, @@ -224,7 +228,7 @@ BOOL Devices::UpdateInstance(JNIEnv *env) AwtWin32GraphicsDevice** rawDevices = newDevices->GetRawArray(); int i; for (i = 0; i < numScreens; ++i) { - J2dTraceLn2(J2D_TRACE_VERBOSE, " hmon[%d]=0x%x", i, monHds[i]); + J2dTraceLn(J2D_TRACE_VERBOSE, " hmon[%d]=0x%x", i, monHds[i]); rawDevices[i] = new AwtWin32GraphicsDevice(i, monHds[i], newDevices); } for (i = 0; i < numScreens; ++i) { @@ -247,8 +251,8 @@ BOOL Devices::UpdateInstance(JNIEnv *env) J2dTraceLn(J2D_TRACE_VERBOSE, " Invalidating removed devices"); for (int i = newNumScreens; i < oldNumScreens; i++) { // removed device, needs to be invalidated - J2dTraceLn1(J2D_TRACE_WARNING, - "Devices::UpdateInstance: device removed: %d", i); + J2dTraceLn(J2D_TRACE_WARNING, + "Devices::UpdateInstance: device removed: %d", i); oldDevices->GetDevice(i)->Invalidate(env); } // Now that we have a new array in place, remove this (possibly the @@ -277,7 +281,7 @@ void Devices::AddReference() J2dTraceLn(J2D_TRACE_INFO, "Devices::AddReference"); CriticalSection::Lock l(arrayLock); refCount++; - J2dTraceLn1(J2D_TRACE_VERBOSE, " refCount=%d", refCount); + J2dTraceLn(J2D_TRACE_VERBOSE, " refCount=%d", refCount); } /** @@ -319,9 +323,9 @@ Devices* Devices::GetInstance() AwtWin32GraphicsDevice *Devices::GetDeviceReference(int index, BOOL adjust) { - J2dTraceLn2(J2D_TRACE_INFO, - "Devices::GetDeviceReference index=%d adjust?=%d", - index, adjust); + J2dTraceLn(J2D_TRACE_INFO, + "Devices::GetDeviceReference index=%d adjust?=%d", + index, adjust); AwtWin32GraphicsDevice * ret = GetDevice(index, adjust); if (ret != NULL) { @@ -339,19 +343,19 @@ AwtWin32GraphicsDevice *Devices::GetDeviceReference(int index, */ AwtWin32GraphicsDevice *Devices::GetDevice(int index, BOOL adjust) { - J2dTraceLn2(J2D_TRACE_INFO, - "Devices::GetDevice index=%d adjust?=%d", - index, adjust); + J2dTraceLn(J2D_TRACE_INFO, + "Devices::GetDevice index=%d adjust?=%d", + index, adjust); if (index < 0 || index >= numDevices) { if (!adjust) { - J2dTraceLn1(J2D_TRACE_WARNING, - "Devices::GetDevice: "\ - "incorrect index %d, returning NULL.", index); + J2dTraceLn(J2D_TRACE_WARNING, + "Devices::GetDevice: "\ + "incorrect index %d, returning NULL.", index); return NULL; } - J2dTraceLn1(J2D_TRACE_WARNING, - "Devices::GetDevice: "\ - "adjusted index %d to 0.", index); + J2dTraceLn(J2D_TRACE_WARNING, + "Devices::GetDevice: "\ + "adjusted index %d to 0.", index); index = 0; } return devices[index]; @@ -385,7 +389,7 @@ int Devices::Release() int refs = --refCount; - J2dTraceLn1(J2D_TRACE_VERBOSE, " refCount=%d", refs); + J2dTraceLn(J2D_TRACE_VERBOSE, " refCount=%d", refs); if (refs == 0) { J2dTraceLn(J2D_TRACE_VERBOSE, " disposing the array"); @@ -407,9 +411,9 @@ int Devices::Release() // (note: can not reference refCount here!) return refs; } else if (refs < 0) { - J2dTraceLn1(J2D_TRACE_ERROR, - "Devices::Release: Negative ref count! refCount=%d", - refs); + J2dTraceLn(J2D_TRACE_ERROR, + "Devices::Release: Negative ref count! refCount=%d", + refs); } return refs; diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h index d2adeca6776..de4d84157c9 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h +++ b/src/java.desktop/windows/native/libawt/windows/awt_Toolkit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,23 +122,23 @@ class CriticalSection { // lock/unlock actions #define CRITICAL_SECTION_ENTER(cs) { \ - J2dTraceLn4(J2D_TRACE_VERBOSE2, \ - "CS.Wait: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ - GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ + J2dTraceLn(J2D_TRACE_VERBOSE2, \ + "CS.Wait: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ + GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ (cs).Enter(); \ - J2dTraceLn4(J2D_TRACE_VERBOSE2, \ - "CS.Enter: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ - GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ + J2dTraceLn(J2D_TRACE_VERBOSE2, \ + "CS.Enter: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ + GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ } #define CRITICAL_SECTION_LEAVE(cs) { \ - J2dTraceLn4(J2D_TRACE_VERBOSE2, \ - "CS.Leave: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ - GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ + J2dTraceLn(J2D_TRACE_VERBOSE2, \ + "CS.Leave: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ + GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ (cs).Leave(); \ - J2dTraceLn4(J2D_TRACE_VERBOSE2, \ - "CS.Left: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ - GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ + J2dTraceLn(J2D_TRACE_VERBOSE2, \ + "CS.Left: tid, cs, file, line = 0x%x, 0x%x, %s, %d", \ + GetCurrentThreadId(), &(cs), __FILE__, __LINE__); \ } // Redefine WinAPI values related to touch input, if OS < Windows 7. diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp index 8a84a28685f..785f1301516 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsDevice.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -843,8 +843,8 @@ int AwtWin32GraphicsDevice::GetGrayness(int deviceIndex) } HDC AwtWin32GraphicsDevice::GetDCFromScreen(int screen) { - J2dTraceLn1(J2D_TRACE_INFO, - "AwtWin32GraphicsDevice::GetDCFromScreen screen=%d", screen); + J2dTraceLn(J2D_TRACE_INFO, + "AwtWin32GraphicsDevice::GetDCFromScreen screen=%d", screen); Devices::InstanceAccess devices; AwtWin32GraphicsDevice *dev = devices->GetDevice(screen); return MakeDCFromMonitor(dev->GetMonitor()); @@ -854,9 +854,9 @@ HDC AwtWin32GraphicsDevice::GetDCFromScreen(int screen) { * If equal, return TRUE */ BOOL AwtWin32GraphicsDevice::AreSameMonitors(HMONITOR mon1, HMONITOR mon2) { - J2dTraceLn2(J2D_TRACE_INFO, - "AwtWin32GraphicsDevice::AreSameMonitors mhnd1=%x mhnd2=%x", - mon1, mon2); + J2dTraceLn(J2D_TRACE_INFO, + "AwtWin32GraphicsDevice::AreSameMonitors mhnd1=%x mhnd2=%x", + mon1, mon2); DASSERT(mon1 != NULL); DASSERT(mon2 != NULL); @@ -885,8 +885,8 @@ BOOL AwtWin32GraphicsDevice::AreSameMonitors(HMONITOR mon1, HMONITOR mon2) { } int AwtWin32GraphicsDevice::GetScreenFromHMONITOR(HMONITOR mon) { - J2dTraceLn1(J2D_TRACE_INFO, - "AwtWin32GraphicsDevice::GetScreenFromHMONITOR mhnd=%x", mon); + J2dTraceLn(J2D_TRACE_INFO, + "AwtWin32GraphicsDevice::GetScreenFromHMONITOR mhnd=%x", mon); DASSERT(mon != NULL); JNIEnv *env = (JNIEnv*) JNU_GetEnv(jvm, JNI_VERSION_1_2); @@ -898,14 +898,14 @@ int AwtWin32GraphicsDevice::GetScreenFromHMONITOR(HMONITOR mon) { for (int i = 0; i < devices->GetNumDevices(); i++) { HMONITOR mhnd = devices->GetDevice(i)->GetMonitor(); if (AreSameMonitors(mon, mhnd)) { - J2dTraceLn1(J2D_TRACE_VERBOSE, " Found device: %d", i); + J2dTraceLn(J2D_TRACE_VERBOSE, " Found device: %d", i); return i; } } - J2dTraceLn1(J2D_TRACE_WARNING, - "AwtWin32GraphicsDevice::GetScreenFromHMONITOR(): "\ - "couldn't find screen for HMONITOR %x, returning default", mon); + J2dTraceLn(J2D_TRACE_WARNING, + "AwtWin32GraphicsDevice::GetScreenFromHMONITOR(): "\ + "couldn't find screen for HMONITOR %x, returning default", mon); return AwtWin32GraphicsDevice::GetDefaultDeviceIndex(); } @@ -1119,9 +1119,9 @@ Java_sun_awt_Win32GraphicsDevice_enterFullScreenExclusive( if (!::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE)) { - J2dTraceLn1(J2D_TRACE_ERROR, - "Error %d setting topmost attribute to fs window", - ::GetLastError()); + J2dTraceLn(J2D_TRACE_ERROR, + "Error %d setting topmost attribute to fs window", + ::GetLastError()); } CATCH_BAD_ALLOC; @@ -1154,9 +1154,9 @@ Java_sun_awt_Win32GraphicsDevice_exitFullScreenExclusive( if (!::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOOWNERZORDER|SWP_NOSIZE)) { - J2dTraceLn1(J2D_TRACE_ERROR, - "Error %d unsetting topmost attribute to fs window", - ::GetLastError()); + J2dTraceLn(J2D_TRACE_ERROR, + "Error %d unsetting topmost attribute to fs window", + ::GetLastError()); } // We should restore alwaysOnTop state as it's anyway dropped here diff --git a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp index 9991427c75e..50591434d4c 100644 --- a/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp +++ b/src/java.desktop/windows/native/libawt/windows/awt_Win32GraphicsEnv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,11 +109,11 @@ BOOL DWMIsCompositionEnabled() { HRESULT res = DwmAPI::DwmIsCompositionEnabled(&bEnabled); if (SUCCEEDED(res)) { bRes = bEnabled; - J2dTraceLn1(J2D_TRACE_VERBOSE, " composition enabled: %d",bRes); + J2dTraceLn(J2D_TRACE_VERBOSE, " composition enabled: %d",bRes); } else { - J2dTraceLn1(J2D_TRACE_ERROR, - "IsDWMCompositionEnabled: error %x when detecting"\ - "if composition is enabled", res); + J2dTraceLn(J2D_TRACE_ERROR, + "IsDWMCompositionEnabled: error %x when detecting"\ + "if composition is enabled", res); } } catch (const DllUtil::Exception &) { J2dTraceLn(J2D_TRACE_ERROR, From 10e6eec9e63c89adc8078aeb27a368a80f793902 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 23 Jun 2025 11:09:11 +0000 Subject: [PATCH 139/213] 8360039: JFR: Improve parser logging of constants Reviewed-by: mgronlun --- .../jfr/internal/consumer/ChunkParser.java | 25 +++++++++++++++---- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java index 67143ee1265..62618c13c5a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -421,14 +421,29 @@ private String textify(Object o) { return o.getClass().getName(); } if (o.getClass().isArray()) { - Object[] array = (Object[]) o; - if (array.length > 0) { - return textify(array[0]) + "[]"; // can it be recursive? - } + return textifyArray((Object[])o); } return String.valueOf(o); } + private String textifyArray(Object[] array) { + int length = array.length; + if (length > 0) { + Object element = array[0]; + if (element != null) { + if (element instanceof String s) { + // Probably an enumeration type, e.g. ThreadState. Remove array indirection + return textify(s); + } + if (element.getClass().isArray()) { + Object[] subArray = (Object[]) element; + return element.getClass().getComponentType().getName() + "[" + subArray.length + "]" + "[" + length + "]"; + } + } + } + return array.getClass().getComponentType().getName() + "[" + length + "]"; + } + private String getName(long id) { Type type = typeMap.get(id); return type == null ? ("unknown(" + id + ")") : type.getName(); From 72679c94ee00c87b9b51233938e5ffa97ef825b1 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 23 Jun 2025 12:46:32 +0000 Subject: [PATCH 140/213] 8360042: GHA: Bump MSVC to 14.44 Reviewed-by: erikj, ihse --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0e64ad78625..8c058440ad7 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -310,7 +310,7 @@ jobs: uses: ./.github/workflows/build-windows.yml with: platform: windows-x64 - msvc-toolset-version: '14.43' + msvc-toolset-version: '14.44' msvc-toolset-architecture: 'x86.x64' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} @@ -322,7 +322,7 @@ jobs: uses: ./.github/workflows/build-windows.yml with: platform: windows-aarch64 - msvc-toolset-version: '14.43' + msvc-toolset-version: '14.44' msvc-toolset-architecture: 'arm64' make-target: 'hotspot' extra-conf-options: '--openjdk-target=aarch64-unknown-cygwin' From c748d358b2569928fb5a03722987c93762c30145 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Mon, 23 Jun 2025 12:49:59 +0000 Subject: [PATCH 141/213] 8360024: Reorganize GC VM operations and implement is_gc_operation Reviewed-by: tschatzl, dholmes --- src/hotspot/share/cds/dynamicArchive.cpp | 4 +- src/hotspot/share/gc/g1/g1VMOperations.cpp | 2 +- src/hotspot/share/gc/g1/g1VMOperations.hpp | 7 +- .../share/gc/parallel/psVMOperations.cpp | 6 +- .../share/gc/parallel/psVMOperations.hpp | 2 +- .../share/gc/serial/serialVMOperations.hpp | 4 +- .../share/gc/shared/gcVMOperations.cpp | 12 ++-- .../share/gc/shared/gcVMOperations.hpp | 69 +++++++++++++------ .../gc/shenandoah/shenandoahVMOperations.hpp | 2 + src/hotspot/share/gc/z/zGeneration.cpp | 8 +++ src/hotspot/share/gc/z/zMark.cpp | 4 ++ src/hotspot/share/runtime/vmOperation.hpp | 4 ++ 12 files changed, 84 insertions(+), 40 deletions(-) diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index c2c4d0bcae3..36afbc65ce3 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -382,11 +382,11 @@ void DynamicArchiveBuilder::gather_array_klasses() { log_debug(aot)("Total array klasses gathered for dynamic archive: %d", DynamicArchive::num_array_klasses()); } -class VM_PopulateDynamicDumpSharedSpace: public VM_GC_Sync_Operation { +class VM_PopulateDynamicDumpSharedSpace: public VM_Heap_Sync_Operation { DynamicArchiveBuilder _builder; public: VM_PopulateDynamicDumpSharedSpace(const char* archive_name) - : VM_GC_Sync_Operation(), _builder(archive_name) {} + : VM_Heap_Sync_Operation(), _builder(archive_name) {} VMOp_Type type() const { return VMOp_PopulateDumpSharedSpace; } void doit() { ResourceMark rm; diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index 69cdd8d5ca6..87fa751691e 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -57,7 +57,7 @@ void VM_G1CollectFull::doit() { VM_G1TryInitiateConcMark::VM_G1TryInitiateConcMark(uint gc_count_before, GCCause::Cause gc_cause) : - VM_GC_Operation(gc_count_before, gc_cause), + VM_GC_Collect_Operation(gc_count_before, gc_cause), _transient_failure(false), _cycle_already_in_progress(false), _whitebox_attached(false), diff --git a/src/hotspot/share/gc/g1/g1VMOperations.hpp b/src/hotspot/share/gc/g1/g1VMOperations.hpp index a201d57db76..f2ac4c6f638 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.hpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.hpp @@ -30,7 +30,7 @@ // VM_operations for the G1 collector. -class VM_G1CollectFull : public VM_GC_Operation { +class VM_G1CollectFull : public VM_GC_Collect_Operation { protected: bool skip_operation() const override; @@ -38,12 +38,12 @@ class VM_G1CollectFull : public VM_GC_Operation { VM_G1CollectFull(uint gc_count_before, uint full_gc_count_before, GCCause::Cause cause) : - VM_GC_Operation(gc_count_before, cause, full_gc_count_before, true) { } + VM_GC_Collect_Operation(gc_count_before, cause, full_gc_count_before, true) { } VMOp_Type type() const override { return VMOp_G1CollectFull; } void doit() override; }; -class VM_G1TryInitiateConcMark : public VM_GC_Operation { +class VM_G1TryInitiateConcMark : public VM_GC_Collect_Operation { bool _transient_failure; bool _cycle_already_in_progress; bool _whitebox_attached; @@ -89,6 +89,7 @@ class VM_G1PauseConcurrent : public VM_Operation { bool doit_prologue() override; void doit_epilogue() override; void doit() override; + bool is_gc_operation() const override { return true; } }; class VM_G1PauseRemark : public VM_G1PauseConcurrent { diff --git a/src/hotspot/share/gc/parallel/psVMOperations.cpp b/src/hotspot/share/gc/parallel/psVMOperations.cpp index dc96d9506e2..98fe1845825 100644 --- a/src/hotspot/share/gc/parallel/psVMOperations.cpp +++ b/src/hotspot/share/gc/parallel/psVMOperations.cpp @@ -52,9 +52,9 @@ static bool is_cause_full(GCCause::Cause cause) { // Only used for System.gc() calls VM_ParallelGCCollect::VM_ParallelGCCollect(uint gc_count, - uint full_gc_count, - GCCause::Cause gc_cause) : - VM_GC_Operation(gc_count, gc_cause, full_gc_count, is_cause_full(gc_cause)) {} + uint full_gc_count, + GCCause::Cause gc_cause) : + VM_GC_Collect_Operation(gc_count, gc_cause, full_gc_count, is_cause_full(gc_cause)) {} void VM_ParallelGCCollect::doit() { ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); diff --git a/src/hotspot/share/gc/parallel/psVMOperations.hpp b/src/hotspot/share/gc/parallel/psVMOperations.hpp index ba896de8680..1a542d59f8e 100644 --- a/src/hotspot/share/gc/parallel/psVMOperations.hpp +++ b/src/hotspot/share/gc/parallel/psVMOperations.hpp @@ -40,7 +40,7 @@ class VM_ParallelCollectForAllocation : public VM_CollectForAllocation { virtual void doit(); }; -class VM_ParallelGCCollect: public VM_GC_Operation { +class VM_ParallelGCCollect: public VM_GC_Collect_Operation { public: VM_ParallelGCCollect(uint gc_count, uint full_gc_count, GCCause::Cause gc_cause); virtual VMOp_Type type() const { return VMOp_ParallelGCCollect; } diff --git a/src/hotspot/share/gc/serial/serialVMOperations.hpp b/src/hotspot/share/gc/serial/serialVMOperations.hpp index 294920f4ae2..31f8c21e61a 100644 --- a/src/hotspot/share/gc/serial/serialVMOperations.hpp +++ b/src/hotspot/share/gc/serial/serialVMOperations.hpp @@ -45,13 +45,13 @@ class VM_SerialCollectForAllocation : public VM_CollectForAllocation { // VM operation to invoke a collection of the heap as a // SerialHeap heap. -class VM_SerialGCCollect: public VM_GC_Operation { +class VM_SerialGCCollect: public VM_GC_Collect_Operation { public: VM_SerialGCCollect(bool full, uint gc_count_before, uint full_gc_count_before, GCCause::Cause gc_cause) - : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, full) {} + : VM_GC_Collect_Operation(gc_count_before, gc_cause, full_gc_count_before, full) {} virtual VMOp_Type type() const { return VMOp_SerialGCCollect; } virtual void doit(); diff --git a/src/hotspot/share/gc/shared/gcVMOperations.cpp b/src/hotspot/share/gc/shared/gcVMOperations.cpp index 7e24e47d4ef..19a81504722 100644 --- a/src/hotspot/share/gc/shared/gcVMOperations.cpp +++ b/src/hotspot/share/gc/shared/gcVMOperations.cpp @@ -48,12 +48,12 @@ #include "gc/g1/g1Policy.hpp" #endif // INCLUDE_G1GC -bool VM_GC_Sync_Operation::doit_prologue() { +bool VM_Heap_Sync_Operation::doit_prologue() { Heap_lock->lock(); return true; } -void VM_GC_Sync_Operation::doit_epilogue() { +void VM_Heap_Sync_Operation::doit_epilogue() { Heap_lock->unlock(); } @@ -114,7 +114,7 @@ bool VM_GC_Operation::doit_prologue() { if (should_use_gclocker()) { GCLocker::block(); } - VM_GC_Sync_Operation::doit_prologue(); + VM_Heap_Sync_Operation::doit_prologue(); // Check invocations if (skip_operation()) { @@ -138,7 +138,7 @@ void VM_GC_Operation::doit_epilogue() { if (Universe::has_reference_pending_list()) { Heap_lock->notify_all(); } - VM_GC_Sync_Operation::doit_epilogue(); + VM_Heap_Sync_Operation::doit_epilogue(); if (should_use_gclocker()) { GCLocker::unblock(); } @@ -205,7 +205,7 @@ VM_CollectForMetadataAllocation::VM_CollectForMetadataAllocation(ClassLoaderData uint gc_count_before, uint full_gc_count_before, GCCause::Cause gc_cause) - : VM_GC_Operation(gc_count_before, gc_cause, full_gc_count_before, true), + : VM_GC_Collect_Operation(gc_count_before, gc_cause, full_gc_count_before, true), _result(nullptr), _size(size), _mdtype(mdtype), _loader_data(loader_data) { assert(_size != 0, "An allocation should always be requested with this operation."); AllocTracer::send_allocation_requiring_gc_event(_size * HeapWordSize, GCId::peek()); @@ -268,7 +268,7 @@ void VM_CollectForMetadataAllocation::doit() { } VM_CollectForAllocation::VM_CollectForAllocation(size_t word_size, uint gc_count_before, GCCause::Cause cause) - : VM_GC_Operation(gc_count_before, cause), _word_size(word_size), _result(nullptr) { + : VM_GC_Collect_Operation(gc_count_before, cause), _word_size(word_size), _result(nullptr) { // Only report if operation was really caused by an allocation. if (_word_size != 0) { AllocTracer::send_allocation_requiring_gc_event(_word_size * HeapWordSize, GCId::peek()); diff --git a/src/hotspot/share/gc/shared/gcVMOperations.hpp b/src/hotspot/share/gc/shared/gcVMOperations.hpp index bc370358ff8..6752e0bc32d 100644 --- a/src/hotspot/share/gc/shared/gcVMOperations.hpp +++ b/src/hotspot/share/gc/shared/gcVMOperations.hpp @@ -37,19 +37,22 @@ // a set of operations (VM_Operation) related to GC. // // VM_Operation -// VM_GC_Sync_Operation +// VM_Heap_Sync_Operation // VM_GC_Operation -// VM_GC_HeapInspection -// VM_PopulateDynamicDumpSharedSpace -// VM_SerialGCCollect -// VM_ParallelGCCollect -// VM_CollectForAllocation -// VM_SerialCollectForAllocation -// VM_ParallelCollectForAllocation +// VM_GC_Collect_Operation +// VM_SerialGCCollect +// VM_ParallelGCCollect +// VM_CollectForAllocation +// VM_SerialCollectForAllocation +// VM_ParallelCollectForAllocation +// VM_CollectForMetadataAllocation +// VM_GC_Service_Operation +// VM_GC_HeapInspection // VM_Verify +// VM_PopulateDynamicDumpSharedSpace // VM_PopulateDumpSharedSpace // -// VM_GC_Sync_Operation +// VM_Heap_Sync_Operation // - implements only synchronization with other VM operations of the // same kind using the Heap_lock, not actually doing a GC. // @@ -84,10 +87,10 @@ // - creates the CDS archive // -class VM_GC_Sync_Operation : public VM_Operation { +class VM_Heap_Sync_Operation : public VM_Operation { public: - VM_GC_Sync_Operation() : VM_Operation() { } + VM_Heap_Sync_Operation() : VM_Operation() { } // Acquires the Heap_lock. virtual bool doit_prologue(); @@ -95,13 +98,13 @@ class VM_GC_Sync_Operation : public VM_Operation { virtual void doit_epilogue(); }; -class VM_Verify : public VM_GC_Sync_Operation { +class VM_Verify : public VM_Heap_Sync_Operation { public: VMOp_Type type() const { return VMOp_Verify; } void doit(); }; -class VM_GC_Operation: public VM_GC_Sync_Operation { +class VM_GC_Operation: public VM_Heap_Sync_Operation { protected: uint _gc_count_before; // gc count before acquiring the Heap_lock uint _full_gc_count_before; // full gc count before acquiring the Heap_lock @@ -115,7 +118,7 @@ class VM_GC_Operation: public VM_GC_Sync_Operation { VM_GC_Operation(uint gc_count_before, GCCause::Cause _cause, uint full_gc_count_before = 0, - bool full = false) : VM_GC_Sync_Operation() { + bool full = false) : VM_Heap_Sync_Operation() { _full = full; _prologue_succeeded = false; _gc_count_before = gc_count_before; @@ -149,31 +152,53 @@ class VM_GC_Operation: public VM_GC_Sync_Operation { static void notify_gc_end(); }; +class VM_GC_Service_Operation : public VM_GC_Operation { +public: + VM_GC_Service_Operation(uint gc_count_before, + GCCause::Cause _cause, + uint full_gc_count_before = 0, + bool full = false) : + VM_GC_Operation(gc_count_before, _cause, full_gc_count_before, full) {} +}; -class VM_GC_HeapInspection: public VM_GC_Operation { +class VM_GC_Collect_Operation : public VM_GC_Operation { +public: + VM_GC_Collect_Operation(uint gc_count_before, + GCCause::Cause _cause, + uint full_gc_count_before = 0, + bool full = false) : + VM_GC_Operation(gc_count_before, _cause, full_gc_count_before, full) {} + + bool is_gc_operation() const { return true; } +}; + + +class VM_GC_HeapInspection : public VM_GC_Service_Operation { private: outputStream* _out; bool _full_gc; uint _parallel_thread_num; + public: VM_GC_HeapInspection(outputStream* out, bool request_full_gc, uint parallel_thread_num = 1) : - VM_GC_Operation(0 /* total collections, dummy, ignored */, - GCCause::_heap_inspection /* GC Cause */, - 0 /* total full collections, dummy, ignored */, - request_full_gc), _out(out), _full_gc(request_full_gc), - _parallel_thread_num(parallel_thread_num) {} + VM_GC_Service_Operation(0 /* total collections, dummy, ignored */, + GCCause::_heap_inspection /* GC Cause */, + 0 /* total full collections, dummy, ignored */, + request_full_gc), _out(out), _full_gc(request_full_gc), + _parallel_thread_num(parallel_thread_num) {} ~VM_GC_HeapInspection() {} virtual VMOp_Type type() const { return VMOp_GC_HeapInspection; } virtual bool skip_operation() const; virtual bool doit_prologue(); virtual void doit(); + protected: bool collect(); }; -class VM_CollectForAllocation : public VM_GC_Operation { +class VM_CollectForAllocation : public VM_GC_Collect_Operation { protected: size_t _word_size; // Size of object to be allocated (in number of words) HeapWord* _result; // Allocation result (null if allocation failed) @@ -186,7 +211,7 @@ class VM_CollectForAllocation : public VM_GC_Operation { } }; -class VM_CollectForMetadataAllocation: public VM_GC_Operation { +class VM_CollectForMetadataAllocation: public VM_GC_Collect_Operation { private: MetaWord* _result; size_t _size; // size of object to be allocated diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp index 09971bb2630..291fadd1887 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp @@ -55,6 +55,8 @@ class VM_ShenandoahOperation : public VM_Operation { void log_active_generation(const char* prefix); bool doit_prologue() override; void doit_epilogue() override; + + bool is_gc_operation() const override { return true; }; }; class VM_ShenandoahReferenceOperation : public VM_ShenandoahOperation { diff --git a/src/hotspot/share/gc/z/zGeneration.cpp b/src/hotspot/share/gc/z/zGeneration.cpp index 534f0195c90..29c4d1fcc6a 100644 --- a/src/hotspot/share/gc/z/zGeneration.cpp +++ b/src/hotspot/share/gc/z/zGeneration.cpp @@ -442,6 +442,10 @@ class VM_ZOperation : public VM_Operation { OopMapCache::try_trigger_cleanup(); } + virtual bool is_gc_operation() const { + return true; + } + bool success() const { return _success; } @@ -1308,6 +1312,10 @@ class ZRendezvousGCThreads: public VM_Operation { return true; } + virtual bool is_gc_operation() const { + return true; + } + void doit() { // Light weight "handshake" of the GC threads SuspendibleThreadSet::synchronize(); diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index 9846f1244ec..de66bbed8df 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -578,6 +578,10 @@ class VM_ZMarkFlushOperation : public VM_Operation { virtual VMOp_Type type() const { return VMOp_ZMarkFlushOperation; } + + virtual bool is_gc_operation() const { + return true; + } }; bool ZMark::flush() { diff --git a/src/hotspot/share/runtime/vmOperation.hpp b/src/hotspot/share/runtime/vmOperation.hpp index ac5d37381f9..89a806bb75d 100644 --- a/src/hotspot/share/runtime/vmOperation.hpp +++ b/src/hotspot/share/runtime/vmOperation.hpp @@ -160,6 +160,10 @@ class VM_Operation : public StackObj { virtual VMOp_Type type() const = 0; virtual bool allow_nested_vm_operations() const { return false; } + // VMOp_Type may belong to a category of the operation. + // Override is_XX_operation() appropriately in subclasses. + virtual bool is_gc_operation() const { return false; } + // You may override skip_thread_oop_barriers to return true if the operation // does not access thread-private oops (including frames). virtual bool skip_thread_oop_barriers() const { return false; } From dfcea0547e7756a546fcf57855d99d46ecfb1925 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Mon, 23 Jun 2025 14:26:02 +0000 Subject: [PATCH 142/213] 8358729: jdk/internal/loader/URLClassPath/ClassnameCharTest.java depends on Applet Reviewed-by: jpai, lancea --- .../URLClassPath/ClassnameCharTest.java | 178 ++++-------------- .../loader/URLClassPath/testclasses.jar | Bin 1173 -> 0 bytes 2 files changed, 40 insertions(+), 138 deletions(-) delete mode 100644 test/jdk/jdk/internal/loader/URLClassPath/testclasses.jar diff --git a/test/jdk/jdk/internal/loader/URLClassPath/ClassnameCharTest.java b/test/jdk/jdk/internal/loader/URLClassPath/ClassnameCharTest.java index 85987ef6f5e..8208e8d9cba 100644 --- a/test/jdk/jdk/internal/loader/URLClassPath/ClassnameCharTest.java +++ b/test/jdk/jdk/internal/loader/URLClassPath/ClassnameCharTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,62 +22,43 @@ */ /* @test - * @bug 4957669 5017871 + * @bug 4957669 5017871 8358729 * @summary cannot load class names containing some JSR 202 characters; * plugin does not escape unicode character in http request * @modules java.base/sun.net.www * jdk.httpserver - * @compile -XDignore.symbol.file=true ClassnameCharTest.java - * @run main ClassnameCharTest + * @run junit ClassnameCharTest */ import java.io.*; +import java.lang.classfile.ClassFile; +import java.lang.constant.ClassDesc; import java.net.*; -import java.security.AccessControlContext; -import java.security.AccessController; import java.security.CodeSource; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; -import java.util.jar.*; import com.sun.net.httpserver.*; import sun.net.www.ParseUtil; +import org.junit.jupiter.api.Test; + public class ClassnameCharTest { - static String FNPrefix = System.getProperty("test.src", ".") + File.separator; - static File classesJar = new File(FNPrefix + "testclasses.jar"); - static HttpServer server; - public static void realMain(String[] args) throws Exception { + private static HttpServer server; + private static final byte[] bytes = + ClassFile.of().build(ClassDesc.of("fo o"), _ -> {}); + + @Test + void testClassName() throws IOException { + // Build the server and set the context server = HttpServer.create(new InetSocketAddress(0), 0); - server.createContext("/", new HttpHandler() { - @Override - public void handle(HttpExchange exchange) { - try { - String filename = exchange.getRequestURI().getPath(); - System.out.println("getRequestURI = " + exchange.getRequestURI()); - System.out.println("filename = " + filename); - try (FileInputStream fis = new FileInputStream(classesJar); - JarInputStream jis = new JarInputStream(fis)) { - JarEntry entry; - while ((entry = jis.getNextJarEntry()) != null) { - if (filename.endsWith(entry.getName())) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - byte[] buf = new byte[8092]; - int count = 0; - while ((count = jis.read(buf)) != -1) - baos.write(buf, 0, count); - exchange.sendResponseHeaders(200, baos.size()); - try (OutputStream os = exchange.getResponseBody()) { - baos.writeTo(os); - } - return; - } - } - fail("Failed to find " + filename); - } - } catch (IOException e) { - unexpected(e); - } + server.createContext("/", exchange -> { + String filename = exchange.getRequestURI().getPath(); + System.out.println("getRequestURI = " + exchange.getRequestURI()); + System.out.println("filename = " + filename); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + baos.write(bytes, 0, bytes.length); + exchange.sendResponseHeaders(200, baos.size()); + try (OutputStream os = exchange.getResponseBody()) { + baos.writeTo(os); } }); server.start(); @@ -87,7 +68,6 @@ public void handle(HttpExchange exchange) { MyURLClassLoader acl = new MyURLClassLoader(base); Class class1 = acl.findClass("fo o"); System.out.println("class1 = " + class1); - pass(); // can't test the following class unless platform in unicode locale // Class class2 = acl.findClass("\u624b\u518c"); // System.out.println("class2 = "+class2); @@ -99,17 +79,15 @@ public void handle(HttpExchange exchange) { static class MyURLClassLoader extends URLClassLoader { private URL base; /* code base URL */ private CodeSource codesource; /* codesource for the base URL */ - private AccessControlContext acc; MyURLClassLoader(URL base) { super(new URL[0]); this.base = base; this.codesource = new CodeSource(base, (java.security.cert.Certificate[]) null); - acc = AccessController.getContext(); } @Override - public Class findClass(String name) throws ClassNotFoundException { + public Class findClass(String name) { int index = name.indexOf(';'); String cookie = ""; if(index != -1) { @@ -117,46 +95,29 @@ public Class findClass(String name) throws ClassNotFoundException { name = name.substring(0, index); } - // check loaded JAR files - try { - return super.findClass(name); - } catch (ClassNotFoundException e) { - } - // Otherwise, try loading the class from the code base URL // final String path = name.replace('.', '/').concat(".class").concat(cookie); String encodedName = ParseUtil.encodePath(name.replace('.', '/'), false); - final String path = (new StringBuffer(encodedName)).append(".class").append(cookie).toString(); + final String path = encodedName + ".class" + cookie; + Exception exc = null; + // try block used for checked exceptions as well as ClassFormatError + // from defineClass call try { - byte[] b = AccessController.doPrivileged( - new PrivilegedExceptionAction() { - public byte[] run() throws IOException { - try { - URL finalURL = new URL(base, path); - - // Make sure the codebase won't be modified - if (base.getProtocol().equals(finalURL.getProtocol()) && - base.getHost().equals(finalURL.getHost()) && - base.getPort() == finalURL.getPort()) { - return getBytes(finalURL); - } - else { - return null; - } - } catch (Exception e) { - return null; - } - } - }, acc); - - if (b != null) { + URL finalURL = new URL(base, path); + // Make sure the codebase won't be modified + if (base.getProtocol().equals(finalURL.getProtocol()) && + base.getHost().equals(finalURL.getHost()) && + base.getPort() == finalURL.getPort()) { + byte[] b = getBytes(finalURL); return defineClass(name, b, 0, b.length, codesource); - } else { - throw new ClassNotFoundException(name); } - } catch (PrivilegedActionException e) { - throw new ClassNotFoundException(name, e.getException()); + // protocol/host/port mismatch, fail with RuntimeException + } catch (Exception underlyingE) { + exc = underlyingE; // Most likely CFE from defineClass } + // Fail if there was either a protocol/host/port mismatch + // or an exception was thrown (which is propagated) + throw new RuntimeException(name, exc); } /* @@ -186,63 +147,4 @@ private static byte[] getBytes(URL url) throws IOException { return b; } } - - //--------------------- Infrastructure --------------------------- - static volatile int passed = 0, failed = 0; - - static boolean pass() { - passed++; - return true; - } - - static boolean fail() { - failed++; - if (server != null) { - server.stop(0); - } - Thread.dumpStack(); - return false; - } - - static boolean fail(String msg) { - System.out.println(msg); - return fail(); - } - - static void unexpected(Throwable t) { - failed++; - if (server != null) { - server.stop(0); - } - t.printStackTrace(); - } - - static boolean check(boolean cond) { - if (cond) { - pass(); - } else { - fail(); - } - return cond; - } - - static boolean equal(Object x, Object y) { - if (x == null ? y == null : x.equals(y)) { - return pass(); - } else { - return fail(x + " not equal to " + y); - } - } - - public static void main(String[] args) throws Throwable { - try { - realMain(args); - } catch (Throwable t) { - unexpected(t); - } - System.out.println("\nPassed = " + passed + " failed = " + failed); - if (failed > 0) { - throw new AssertionError("Some tests failed"); - } - } } diff --git a/test/jdk/jdk/internal/loader/URLClassPath/testclasses.jar b/test/jdk/jdk/internal/loader/URLClassPath/testclasses.jar deleted file mode 100644 index 0069eee84a063e559916268140dda69e15837779..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1173 zcmWIWW@Zs#-~hrO1sw(qNPv@pg~8V~#8KDN&rSc|DFy~+h5&DN4v-2asImZ@nni#r z;F^6M{XE@VgG2Ou-9G!CIql=Et9OytTUYDcne&^246YbIcv__A<*VcAd$DvC3#Y_O zNzDwF>CZHOq^XHN6%QAizT}yhcEvN**O{M+J{B>8U9oEM-5eL79UzQw#f_dy6fXz? zWe+bq)Oo1;@X|wVhkEpqa}tY-a|2F$9d;10y}U(o_OWf-u9dTv=L$aFr_`aq;n?c& z{j$}GDJGmRUB0lhT%3QgwTs*S!2b*91@hfCNT(OdKc81D|M}zJZ+r>jv-xsDPOn(_ zE`gD^eUaL6CHL-w_kt&0`ppxz+&V!+?wI(bh0j)d%uAWP(C7S71C=EvSCy{v_z9%H z^pIOAv!>?m-THfWZ+ebSEjVa+eB+ZONo|?cde=6*OJdHI`gA%u*;aip$*XL8il$rrG`TAkAJ~5^?%8a6 z;;7uS$7lDL8~^?H^AA%&Q!|5|R%%Ef_lCYIhrs6K=EWx;%zqVf+n7!N4Uc4(__H{} zkl$9J*Sk}eY_hiO;?z95_Kc3RfkAi98og4!Y3j#jJYHEdg-J$RW;Rpwjb}FmZycR> zz%FWurD5*jfb+kVEN34*<@WrX;T0K)(_a*&Y|gLs$`IVVz-jY)ty?bJXZpQ8kmjXk z+jh*}fO-DY$T>p#Z}e63-GWWG*_O|!x}*}#v);;CW|2$$r2R}0`z&u7rRsj_sag4( z@0%0jUGHn<3*5`TuK#)>knv-e(|6u^-y0uI3S5{sNilQ2#hieLZEOEBfihF$g4cId zfZ;k79JY*1A`GZ`5th+Fc@Y)BGZ!dl26&@tMa~_doQMFnKqg!(Qocks0hEi7BOR2B r5a2M7iJ7O6^@EZIvd2J40|E4aenKRa0B=?{kQ@sTeg)E9%pe{B#59*- From 9c3eaa49f7f8c6ade7319064566c0370e955f631 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Mon, 23 Jun 2025 16:16:28 +0000 Subject: [PATCH 143/213] 8359732: Make standard i/o encoding related system properties `StaticProperty` Reviewed-by: rriggs, alanb, vyazici --- .../share/classes/java/io/Console.java | 5 ++- src/java.base/share/classes/java/lang/IO.java | 4 +- .../jdk/internal/util/StaticProperty.java | 41 +++++++++++++++---- .../sun/security/tools/keytool/Main.java | 4 +- .../security/util/ConsoleCallbackHandler.java | 4 +- .../jgss/wrapper/SunNativeProvider.java | 5 +-- .../incubator/vector/VectorMathLibrary.java | 3 +- 7 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java index cedb6124a31..838334a0901 100644 --- a/src/java.base/share/classes/java/io/Console.java +++ b/src/java.base/share/classes/java/io/Console.java @@ -31,6 +31,7 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.io.JdkConsoleImpl; import jdk.internal.io.JdkConsoleProvider; +import jdk.internal.util.StaticProperty; import sun.nio.cs.UTF_8; /** @@ -555,9 +556,9 @@ private static UnsupportedOperationException newUnsupportedOperationException() private static final boolean istty = istty(); private static final Charset STDIN_CHARSET = - Charset.forName(System.getProperty("stdin.encoding"), UTF_8.INSTANCE); + Charset.forName(StaticProperty.stdinEncoding(), UTF_8.INSTANCE); private static final Charset STDOUT_CHARSET = - Charset.forName(System.getProperty("stdout.encoding"), UTF_8.INSTANCE); + Charset.forName(StaticProperty.stdoutEncoding(), UTF_8.INSTANCE); private static final Console cons = instantiateConsole(); static { // Set up JavaIOAccess in SharedSecrets diff --git a/src/java.base/share/classes/java/lang/IO.java b/src/java.base/share/classes/java/lang/IO.java index 4630d8a3be2..c4586f6478a 100644 --- a/src/java.base/share/classes/java/lang/IO.java +++ b/src/java.base/share/classes/java/lang/IO.java @@ -32,6 +32,8 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import jdk.internal.util.StaticProperty; + /** * A collection of static methods that provide convenient access to {@link System#in} * and {@link System#out} for line-oriented input and output. @@ -187,7 +189,7 @@ public static String readln(String prompt) { */ static synchronized BufferedReader reader() { if (br == null) { - String enc = System.getProperty("stdin.encoding", ""); + String enc = StaticProperty.stdinEncoding(); Charset cs = Charset.forName(enc, StandardCharsets.UTF_8); br = new BufferedReader(new InputStreamReader(System.in, cs)); } diff --git a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java index abe2dafa3b7..4fb3ae7a184 100644 --- a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java +++ b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ import java.util.Properties; /** - * System Property access for internal use only. + * System Property access for `java.base` module internal use only. * Read-only access to System property values initialized during Phase 1 * are cached. Setting, clearing, or modifying the value using * {@link System#setProperty} or {@link System#getProperties()} is ignored. @@ -48,8 +48,11 @@ public final class StaticProperty { private static final String JAVA_IO_TMPDIR; private static final String NATIVE_ENCODING; private static final String FILE_ENCODING; - private static final String JAVA_PROPERTIES_DATE; + private static final String STDIN_ENCODING; + private static final String STDERR_ENCODING; + private static final String STDOUT_ENCODING; private static final String SUN_JNU_ENCODING; + private static final String JAVA_PROPERTIES_DATE; private static final String JAVA_LOCALE_USE_OLD_ISO_CODES; private static final String OS_NAME; private static final String OS_ARCH; @@ -86,8 +89,11 @@ private StaticProperty() {} JDK_SERIAL_FILTER_FACTORY = getProperty(props, "jdk.serialFilterFactory", null); NATIVE_ENCODING = getProperty(props, "native.encoding"); FILE_ENCODING = getProperty(props, "file.encoding"); - JAVA_PROPERTIES_DATE = getProperty(props, "java.properties.date", null); + STDIN_ENCODING = getProperty(props, "stdin.encoding"); + STDERR_ENCODING = getProperty(props, "stderr.encoding"); + STDOUT_ENCODING = getProperty(props, "stdout.encoding"); SUN_JNU_ENCODING = getProperty(props, "sun.jnu.encoding"); + JAVA_PROPERTIES_DATE = getProperty(props, "java.properties.date", null); JAVA_LOCALE_USE_OLD_ISO_CODES = getProperty(props, "java.locale.useOldISOCodes", ""); OS_NAME = getProperty(props, "os.name"); OS_ARCH = getProperty(props, "os.arch"); @@ -218,10 +224,24 @@ public static String fileEncoding() { } /** - * {@return the {@code java.properties.date} system property} + * {@return the {@code stdin.encoding} system property} */ - public static String javaPropertiesDate() { - return JAVA_PROPERTIES_DATE; + public static String stdinEncoding() { + return STDIN_ENCODING; + } + + /** + * {@return the {@code stderr.encoding} system property} + */ + public static String stderrEncoding() { + return STDERR_ENCODING; + } + + /** + * {@return the {@code stdout.encoding} system property} + */ + public static String stdoutEncoding() { + return STDOUT_ENCODING; } /** @@ -231,6 +251,13 @@ public static String jnuEncoding() { return SUN_JNU_ENCODING; } + /** + * {@return the {@code java.properties.date} system property} + */ + public static String javaPropertiesDate() { + return JAVA_PROPERTIES_DATE; + } + /** * {@return the {@code java.locale.useOldISOCodes} system property} */ diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Main.java b/src/java.base/share/classes/sun/security/tools/keytool/Main.java index 6bea35a996f..8c6cd139a0d 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Main.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Main.java @@ -60,6 +60,8 @@ import javax.security.auth.x500.X500Principal; import java.util.Base64; +import jdk.internal.util.StaticProperty; + import sun.security.pkcs12.PKCS12KeyStore; import sun.security.provider.certpath.CertPathConstraintsParameters; import sun.security.util.*; @@ -3549,7 +3551,7 @@ private String inputStringFromStdin(String prompt) throws Exception { private static BufferedReader stdinAwareReader(InputStream in) { InputStreamReader reader = in == System.in - ? new InputStreamReader(in, Charset.forName(System.getProperty("stdin.encoding"), Charset.defaultCharset())) + ? new InputStreamReader(in, Charset.forName(StaticProperty.stdinEncoding(), Charset.defaultCharset())) : new InputStreamReader(in); return new BufferedReader(reader); } diff --git a/src/java.base/share/classes/sun/security/util/ConsoleCallbackHandler.java b/src/java.base/share/classes/sun/security/util/ConsoleCallbackHandler.java index 66140824bec..725a78c39c8 100644 --- a/src/java.base/share/classes/sun/security/util/ConsoleCallbackHandler.java +++ b/src/java.base/share/classes/sun/security/util/ConsoleCallbackHandler.java @@ -25,6 +25,8 @@ package sun.security.util; +import jdk.internal.util.StaticProperty; + import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.ConfirmationCallback; @@ -131,7 +133,7 @@ public void handle(Callback[] callbacks) /* Reads a line of input */ private String readLine() throws IOException { - Charset charset = Charset.forName(System.getProperty("stdin.encoding"), Charset.defaultCharset()); + Charset charset = Charset.forName(StaticProperty.stdinEncoding(), Charset.defaultCharset()); InputStreamReader reader = new InputStreamReader(System.in, charset); String result = new BufferedReader(reader).readLine(); if (result == null) { diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java index 2da15b8b6a6..ad24432f188 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/wrapper/SunNativeProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.security.Provider; import jdk.internal.util.OperatingSystem; -import jdk.internal.util.StaticProperty; import org.ietf.jgss.Oid; import static sun.security.util.SecurityConstants.PROVIDER_VER; @@ -95,7 +94,7 @@ private static Oid[] getMechOIDs() { }; case WINDOWS -> new String[]{ // Full path needed, DLL is in jre/bin - StaticProperty.javaHome() + "\\bin\\sspi_bridge.dll", + System.getProperty("java.home") + "\\bin\\sspi_bridge.dll", }; case AIX -> new String[]{ "/opt/freeware/lib64/libgssapi_krb5.so", diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMathLibrary.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMathLibrary.java index 4729235e2d9..ecd03ab9124 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMathLibrary.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/VectorMathLibrary.java @@ -24,7 +24,6 @@ */ package jdk.incubator.vector; -import jdk.internal.util.StaticProperty; import jdk.internal.vm.annotation.DontInline; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; @@ -70,7 +69,7 @@ static Library getInstance() { } static String getDefaultName() { - return switch (StaticProperty.osArch()) { + return switch (System.getProperty("os.arch")) { case "amd64", "x86_64" -> SVML; case "aarch64", "riscv64" -> SLEEF; default -> JAVA; From 6df0f5e390ecf874c1eca7284c51efa65ce23737 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Mon, 23 Jun 2025 18:19:01 +0000 Subject: [PATCH 144/213] 8360281: VMError::error_string has incorrect format usage Reviewed-by: coleenp --- src/hotspot/share/utilities/vmError.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 7d1b17d5deb..448df20c44e 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -266,7 +266,7 @@ char* VMError::error_string(char* buf, int buflen) { if (signame) { jio_snprintf(buf, buflen, "%s (0x%x) at pc=" PTR_FORMAT ", pid=%d, tid=%zu", - signame, _id, _pc, + signame, _id, p2i(_pc), os::current_process_id(), os::current_thread_id()); } else if (_filename != nullptr && _lineno > 0) { // skip directory names From 2a70a6dc58ebd0085c34fee899667758b827c55c Mon Sep 17 00:00:00 2001 From: Nizar Benalla Date: Mon, 23 Jun 2025 22:24:57 +0000 Subject: [PATCH 145/213] 8346886: Add since checker test to jdk.management.jfr Reviewed-by: egahlin --- .../JdkManagementJfrCheckSince.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 test/jdk/tools/sincechecker/modules/jdk.management.jfr/JdkManagementJfrCheckSince.java diff --git a/test/jdk/tools/sincechecker/modules/jdk.management.jfr/JdkManagementJfrCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.management.jfr/JdkManagementJfrCheckSince.java new file mode 100644 index 00000000000..37dd6f29db1 --- /dev/null +++ b/test/jdk/tools/sincechecker/modules/jdk.management.jfr/JdkManagementJfrCheckSince.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8346886 + * @summary Test for `@since` in jdk.management.jfr module + * @library /test/lib /test/jdk/tools/sincechecker + * @run main SinceChecker jdk.management.jfr + */ From bcad87eacbd7fbfd3254479b7e061bab34e64aec Mon Sep 17 00:00:00 2001 From: Manukumar V S Date: Tue, 24 Jun 2025 02:20:49 +0000 Subject: [PATCH 146/213] 8358697: TextLayout/MyanmarTextTest.java passes if no Myanmar font is found Reviewed-by: aivanov --- .../awt/font/TextLayout/MyanmarTextTest.java | 45 ++++++++----------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java b/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java index 32c748ce80f..20db89ff0c6 100644 --- a/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java +++ b/test/jdk/java/awt/font/TextLayout/MyanmarTextTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,15 @@ * @key headful * @summary Verifies that Myanmar script is rendered correctly: * two characters combined into one glyph + * @library /test/lib + * @build jtreg.SkippedException * @run main MyanmarTextTest */ import java.awt.Font; import java.awt.GraphicsEnvironment; import java.util.Arrays; +import java.util.List; import javax.swing.BorderFactory; import javax.swing.BoxLayout; import javax.swing.JFrame; @@ -45,12 +48,16 @@ import javax.swing.text.BadLocationException; import javax.swing.text.Position; +import jtreg.SkippedException; + public class MyanmarTextTest { private static final String TEXT = "\u1000\u103C"; - private static final String FONT_WINDOWS = "Myanmar Text"; - private static final String FONT_LINUX = "Padauk"; - private static final String FONT_MACOS = "Myanmar MN"; + private static final List FONT_CANDIDATES = + List.of("Myanmar MN", + "Padauk", + "Myanmar Text", + "Noto Sans Myanmar"); private static final String FONT_NAME = selectFontName(); @@ -61,12 +68,8 @@ public class MyanmarTextTest { public static void main(String[] args) throws Exception { if (FONT_NAME == null) { - System.err.println("Unsupported OS: exiting"); - return; - } - if (!fontExists()) { - System.err.println("Required font is not installed: " + FONT_NAME); - return; + throw new SkippedException("No suitable font found out of the list: " + + String.join(", ", FONT_CANDIDATES)); } try { @@ -130,22 +133,12 @@ private void checkPositions() { } private static String selectFontName() { - String osName = System.getProperty("os.name").toLowerCase(); - if (osName.contains("windows")) { - return FONT_WINDOWS; - } else if (osName.contains("linux")) { - return FONT_LINUX; - } else if (osName.contains("mac")) { - return FONT_MACOS; - } else { - return null; - } + return Arrays.stream(GraphicsEnvironment + .getLocalGraphicsEnvironment() + .getAvailableFontFamilyNames()) + .filter(FONT_CANDIDATES::contains) + .findFirst() + .orElse(null); } - private static boolean fontExists() { - String[] fontFamilyNames = GraphicsEnvironment - .getLocalGraphicsEnvironment() - .getAvailableFontFamilyNames(); - return Arrays.asList(fontFamilyNames).contains(FONT_NAME); - } } From a350a1115a32ae1aa013a22c05a009051a674793 Mon Sep 17 00:00:00 2001 From: Chad Rakoczy Date: Tue, 24 Jun 2025 02:34:53 +0000 Subject: [PATCH 147/213] 8358655: AArch64: Simplify Interpreter::profile_taken_branch Reviewed-by: shade, aph --- .../cpu/aarch64/interp_masm_aarch64.cpp | 23 ++++--------------- .../cpu/aarch64/interp_masm_aarch64.hpp | 2 +- .../cpu/aarch64/templateTable_aarch64.cpp | 5 +--- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index 35d6ebfae4b..e14829b7c89 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -1016,31 +1016,16 @@ void InterpreterMacroAssembler::update_mdp_for_ret(Register return_bci) { } -void InterpreterMacroAssembler::profile_taken_branch(Register mdp, - Register bumped_count) { +void InterpreterMacroAssembler::profile_taken_branch(Register mdp) { if (ProfileInterpreter) { Label profile_continue; // If no method data exists, go to profile_continue. - // Otherwise, assign to mdp test_method_data_pointer(mdp, profile_continue); // We are taking a branch. Increment the taken count. - // We inline increment_mdp_data_at to return bumped_count in a register - //increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); - Address data(mdp, in_bytes(JumpData::taken_offset())); - ldr(bumped_count, data); - assert(DataLayout::counter_increment == 1, - "flow-free idiom only works with 1"); - // Intel does this to catch overflow - // addptr(bumped_count, DataLayout::counter_increment); - // sbbptr(bumped_count, 0); - // so we do this - adds(bumped_count, bumped_count, DataLayout::counter_increment); - Label L; - br(Assembler::CS, L); // skip store if counter overflow - str(bumped_count, data); - bind(L); + increment_mdp_data_at(mdp, in_bytes(JumpData::taken_offset())); + // The method data pointer needs to be updated to reflect the new target. update_mdp_by_offset(mdp, in_bytes(JumpData::displacement_offset())); bind(profile_continue); @@ -1055,7 +1040,7 @@ void InterpreterMacroAssembler::profile_not_taken_branch(Register mdp) { // If no method data exists, go to profile_continue. test_method_data_pointer(mdp, profile_continue); - // We are taking a branch. Increment the not taken count. + // We are not taking a branch. Increment the not taken count. increment_mdp_data_at(mdp, in_bytes(BranchData::not_taken_offset())); // The method data pointer needs to be updated to correspond to diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp index 447d4f8244e..e896a2a9430 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp @@ -276,7 +276,7 @@ class InterpreterMacroAssembler: public MacroAssembler { // narrow int return value void narrow(Register result); - void profile_taken_branch(Register mdp, Register bumped_count); + void profile_taken_branch(Register mdp); void profile_not_taken_branch(Register mdp); void profile_call(Register mdp); void profile_final_call(Register mdp); diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index fcfe153a9a5..2ccde98d98d 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -1759,7 +1759,7 @@ void TemplateTable::float_cmp(bool is_float, int unordered_result) void TemplateTable::branch(bool is_jsr, bool is_wide) { - __ profile_taken_branch(r0, r1); + __ profile_taken_branch(r0); const ByteSize be_offset = MethodCounters::backedge_counter_offset() + InvocationCounter::counter_offset(); const ByteSize inv_offset = MethodCounters::invocation_counter_offset() + @@ -1809,7 +1809,6 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) if (UseLoopCounter) { // increment backedge counter for backward branches // r0: MDO - // w1: MDO bumped taken-count // r2: target offset __ cmp(r2, zr); __ br(Assembler::GT, dispatch); // count only if backward branch @@ -1820,12 +1819,10 @@ void TemplateTable::branch(bool is_jsr, bool is_wide) __ ldr(rscratch1, Address(rmethod, Method::method_counters_offset())); __ cbnz(rscratch1, has_counters); __ push(r0); - __ push(r1); __ push(r2); __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::build_method_counters), rmethod); __ pop(r2); - __ pop(r1); __ pop(r0); __ ldr(rscratch1, Address(rmethod, Method::method_counters_offset())); __ cbz(rscratch1, dispatch); // No MethodCounters allocated, OutOfMemory From 34412da52b41e9374168e67e3b6129576c8e4402 Mon Sep 17 00:00:00 2001 From: Anjian Wen Date: Tue, 24 Jun 2025 03:08:50 +0000 Subject: [PATCH 148/213] 8360179: RISC-V: Only enable BigInteger intrinsics when AvoidUnalignedAccess == false Reviewed-by: fjiang, fyang --- .../cpu/riscv/macroAssembler_riscv.cpp | 101 +----------------- .../cpu/riscv/macroAssembler_riscv.hpp | 4 - src/hotspot/cpu/riscv/vm_version_riscv.cpp | 36 +++++-- 3 files changed, 30 insertions(+), 111 deletions(-) diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index d44e7daa563..a72a2a50fd7 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -5341,42 +5341,6 @@ void MacroAssembler::add2_with_carry(Register final_dest_hi, Register dest_hi, R add(final_dest_hi, dest_hi, carry); } -/** - * Multiply 32 bit by 32 bit first loop. - */ -void MacroAssembler::multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart, - Register y, Register y_idx, Register z, - Register carry, Register product, - Register idx, Register kdx) { - // jlong carry, x[], y[], z[]; - // for (int idx=ystart, kdx=ystart+1+xstart; idx >= 0; idx--, kdx--) { - // long product = y[idx] * x[xstart] + carry; - // z[kdx] = (int)product; - // carry = product >>> 32; - // } - // z[xstart] = (int)carry; - - Label L_first_loop, L_first_loop_exit; - blez(idx, L_first_loop_exit); - - shadd(t0, xstart, x, t0, LogBytesPerInt); - lwu(x_xstart, Address(t0, 0)); - - bind(L_first_loop); - subiw(idx, idx, 1); - shadd(t0, idx, y, t0, LogBytesPerInt); - lwu(y_idx, Address(t0, 0)); - mul(product, x_xstart, y_idx); - add(product, product, carry); - srli(carry, product, 32); - subiw(kdx, kdx, 1); - shadd(t0, kdx, z, t0, LogBytesPerInt); - sw(product, Address(t0, 0)); - bgtz(idx, L_first_loop); - - bind(L_first_loop_exit); -} - /** * Multiply 64 bit by 64 bit first loop. */ @@ -5593,77 +5557,16 @@ void MacroAssembler::multiply_to_len(Register x, Register xlen, Register y, Regi const Register carry = tmp5; const Register product = xlen; const Register x_xstart = tmp0; + const Register jdx = tmp1; mv(idx, ylen); // idx = ylen; addw(kdx, xlen, ylen); // kdx = xlen+ylen; mv(carry, zr); // carry = 0; - Label L_multiply_64_x_64_loop, L_done; - + Label L_done; subiw(xstart, xlen, 1); bltz(xstart, L_done); - const Register jdx = tmp1; - - if (AvoidUnalignedAccesses) { - int base_offset = arrayOopDesc::base_offset_in_bytes(T_INT); - assert((base_offset % (UseCompactObjectHeaders ? 4 : - (UseCompressedClassPointers ? 8 : 4))) == 0, "Must be"); - - if ((base_offset % 8) == 0) { - // multiply_64_x_64_loop emits 8-byte load/store to access two elements - // at a time from int arrays x and y. When base_offset is 8 bytes, these - // accesses are naturally aligned if both xlen and ylen are even numbers. - orr(t0, xlen, ylen); - test_bit(t0, t0, 0); - beqz(t0, L_multiply_64_x_64_loop); - } - - Label L_second_loop_unaligned, L_third_loop, L_third_loop_exit; - - multiply_32_x_32_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx); - shadd(t0, xstart, z, t0, LogBytesPerInt); - sw(carry, Address(t0, 0)); - - bind(L_second_loop_unaligned); - mv(carry, zr); - mv(jdx, ylen); - subiw(xstart, xstart, 1); - bltz(xstart, L_done); - - subi(sp, sp, 2 * wordSize); - sd(z, Address(sp, 0)); - sd(zr, Address(sp, wordSize)); - shadd(t0, xstart, z, t0, LogBytesPerInt); - addi(z, t0, 4); - shadd(t0, xstart, x, t0, LogBytesPerInt); - lwu(product, Address(t0, 0)); - - blez(jdx, L_third_loop_exit); - - bind(L_third_loop); - subiw(jdx, jdx, 1); - shadd(t0, jdx, y, t0, LogBytesPerInt); - lwu(t0, Address(t0, 0)); - mul(t1, t0, product); - add(t0, t1, carry); - shadd(tmp6, jdx, z, t1, LogBytesPerInt); - lwu(t1, Address(tmp6, 0)); - add(t0, t0, t1); - sw(t0, Address(tmp6, 0)); - srli(carry, t0, 32); - bgtz(jdx, L_third_loop); - - bind(L_third_loop_exit); - ld(z, Address(sp, 0)); - addi(sp, sp, 2 * wordSize); - shadd(t0, xstart, z, t0, LogBytesPerInt); - sw(carry, Address(t0, 0)); - - j(L_second_loop_unaligned); - } - - bind(L_multiply_64_x_64_loop); multiply_64_x_64_loop(x, xstart, x_xstart, y, y_idx, z, carry, product, idx, kdx); Label L_second_loop_aligned; diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index e61d9d5e097..8968f3858af 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -1384,10 +1384,6 @@ class MacroAssembler: public Assembler { void adc(Register dst, Register src1, Register src2, Register carry); void add2_with_carry(Register final_dest_hi, Register dest_hi, Register dest_lo, Register src1, Register src2, Register carry); - void multiply_32_x_32_loop(Register x, Register xstart, Register x_xstart, - Register y, Register y_idx, Register z, - Register carry, Register product, - Register idx, Register kdx); void multiply_64_x_64_loop(Register x, Register xstart, Register x_xstart, Register y, Register y_idx, Register z, Register carry, Register product, diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 947d78477da..46324815001 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -325,20 +325,40 @@ void VM_Version::c2_initialize() { FLAG_SET_DEFAULT(UseMulAddIntrinsic, true); } - if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { - FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); + if (!AvoidUnalignedAccesses) { + if (FLAG_IS_DEFAULT(UseMultiplyToLenIntrinsic)) { + FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, true); + } + } else if (UseMultiplyToLenIntrinsic) { + warning("Intrinsics for BigInteger.multiplyToLen() not available on this CPU."); + FLAG_SET_DEFAULT(UseMultiplyToLenIntrinsic, false); } - if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { - FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, true); + if (!AvoidUnalignedAccesses) { + if (FLAG_IS_DEFAULT(UseSquareToLenIntrinsic)) { + FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, true); + } + } else if (UseSquareToLenIntrinsic) { + warning("Intrinsics for BigInteger.squareToLen() not available on this CPU."); + FLAG_SET_DEFAULT(UseSquareToLenIntrinsic, false); } - if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { - FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true); + if (!AvoidUnalignedAccesses) { + if (FLAG_IS_DEFAULT(UseMontgomeryMultiplyIntrinsic)) { + FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, true); + } + } else if (UseMontgomeryMultiplyIntrinsic) { + warning("Intrinsics for BigInteger.montgomeryMultiply() not available on this CPU."); + FLAG_SET_DEFAULT(UseMontgomeryMultiplyIntrinsic, false); } - if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { - FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true); + if (!AvoidUnalignedAccesses) { + if (FLAG_IS_DEFAULT(UseMontgomerySquareIntrinsic)) { + FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, true); + } + } else if (UseMontgomerySquareIntrinsic) { + warning("Intrinsics for BigInteger.montgomerySquare() not available on this CPU."); + FLAG_SET_DEFAULT(UseMontgomerySquareIntrinsic, false); } // Adler32 From 9af36b13c52b60274507a90874b8fb41fc3586f8 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Tue, 24 Jun 2025 05:19:18 +0000 Subject: [PATCH 149/213] 8360307: Problemlist tools/sincechecker/modules/jdk.management.jfr/JdkManagementJfrCheckSince.java Reviewed-by: dholmes, liach --- test/jdk/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index bf8d285c355..ed709e1b7cc 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -838,3 +838,5 @@ java/awt/Modal/NativeDialogToFrontBackTest.java 7188049 windows-all,linux-all # jdk_since_checks tools/sincechecker/modules/java.base/JavaBaseCheckSince.java 8358627 generic-all +tools/sincechecker/modules/jdk.management.jfr/JdkManagementJfrCheckSince.java 8354921 generic-all + From dbbfa76b7335291b4bb9d8de6e7db8e6cec144ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Tue, 24 Jun 2025 06:09:17 +0000 Subject: [PATCH 150/213] 8131136: java/awt/font/JNICheck/JNICheck.sh issue warning on core-libs code Reviewed-by: aivanov, prr, serb --- src/java.base/share/native/libnet/net_util.c | 2 +- test/jdk/java/awt/font/JNICheck/JNICheck.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/native/libnet/net_util.c b/src/java.base/share/native/libnet/net_util.c index 9c0f14b0d90..b61ead11dd5 100644 --- a/src/java.base/share/native/libnet/net_util.c +++ b/src/java.base/share/native/libnet/net_util.c @@ -74,7 +74,7 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) s = (*env)->NewStringUTF(env, "java.net.preferIPv4Stack"); CHECK_NULL_RETURN(s, JNI_VERSION_1_2); preferIPv4Stack = (*env)->CallStaticBooleanMethod(env, iCls, mid, s); - + JNU_CHECK_EXCEPTION_RETURN(env, JNI_VERSION_1_2); /* * Since we have initialized and loaded the socket library we will * check now whether we have IPv6 on this platform and if the diff --git a/test/jdk/java/awt/font/JNICheck/JNICheck.sh b/test/jdk/java/awt/font/JNICheck/JNICheck.sh index cc019e72d56..5464a5e3fc1 100644 --- a/test/jdk/java/awt/font/JNICheck/JNICheck.sh +++ b/test/jdk/java/awt/font/JNICheck/JNICheck.sh @@ -1,6 +1,6 @@ #!/bin/ksh -p # -# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ else fi $JAVA_HOME/bin/java ${TESTVMOPTS} \ - -cp "${CP}" -Xcheck:jni JNICheck | grep -v SIG | grep -v Signal | grep -v Handler | grep -v jsig | grep -v CallStatic > "${CP}"/log.txt + -cp "${CP}" -Xcheck:jni JNICheck | grep -v SIG | grep -v Signal | grep -v Handler | grep -v jsig > "${CP}"/log.txt # any messages logged may indicate a failure. if [ -s "${CP}"/log.txt ]; then From f6ff38ab4292762a35fb151b6886e58df60824d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Tue, 24 Jun 2025 06:55:05 +0000 Subject: [PATCH 151/213] 8353815: [ubsan] compilationPolicy.cpp: division by zero related to tiered compilation flags Reviewed-by: mbaesken, kvn --- src/hotspot/share/compiler/compilationPolicy.cpp | 2 +- src/hotspot/share/compiler/compiler_globals.hpp | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index 1240fd21bbf..02dec8d957b 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -385,7 +385,7 @@ class CallPredicate : AllStatic { double CompilationPolicy::threshold_scale(CompLevel level, int feedback_k) { int comp_count = compiler_count(level); - if (comp_count > 0) { + if (comp_count > 0 && feedback_k > 0) { double queue_size = CompileBroker::queue_size(level); double k = (double)queue_size / ((double)feedback_k * (double)comp_count) + 1; diff --git a/src/hotspot/share/compiler/compiler_globals.hpp b/src/hotspot/share/compiler/compiler_globals.hpp index 3c47b991120..605c0c58869 100644 --- a/src/hotspot/share/compiler/compiler_globals.hpp +++ b/src/hotspot/share/compiler/compiler_globals.hpp @@ -234,12 +234,14 @@ \ product(intx, Tier3LoadFeedback, 5, \ "Tier 3 thresholds will increase twofold when C1 queue size " \ - "reaches this amount per compiler thread") \ + "reaches this amount per compiler thread" \ + "Passing 0 disables the threshold scaling") \ range(0, max_jint) \ \ product(intx, Tier4LoadFeedback, 3, \ "Tier 4 thresholds will increase twofold when C2 queue size " \ - "reaches this amount per compiler thread") \ + "reaches this amount per compiler thread" \ + "Passing 0 disables the threshold scaling") \ range(0, max_jint) \ \ product(intx, TieredCompileTaskTimeout, 50, \ @@ -263,11 +265,11 @@ \ product(intx, TieredRateUpdateMinTime, 1, \ "Minimum rate sampling interval (in milliseconds)") \ - range(0, max_intx) \ + range(1, max_intx) \ \ product(intx, TieredRateUpdateMaxTime, 25, \ "Maximum rate sampling interval (in milliseconds)") \ - range(0, max_intx) \ + range(1, max_intx) \ \ product(double, Tier0ProfileDelayFactor, 100.0, DIAGNOSTIC, \ "Delay profiling/compiling of methods that were " \ From 03d66d9ee239d77d54912f4fa3074560ac2a8101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Tue, 24 Jun 2025 07:00:45 +0000 Subject: [PATCH 152/213] 8358572: C1 hits "need debug information" assert with -XX:-DeoptC1 Reviewed-by: shade, aph --- src/hotspot/share/c1/c1_Compilation.cpp | 2 +- src/hotspot/share/c1/c1_GraphBuilder.cpp | 5 ++--- src/hotspot/share/c1/c1_globals.hpp | 3 --- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index 3e2171eee08..bb5ceb0106b 100644 --- a/src/hotspot/share/c1/c1_Compilation.cpp +++ b/src/hotspot/share/c1/c1_Compilation.cpp @@ -668,7 +668,7 @@ ciKlass* Compilation::cha_exact_type(ciType* type) { if (type != nullptr && type->is_loaded() && type->is_instance_klass()) { ciInstanceKlass* ik = type->as_instance_klass(); assert(ik->exact_klass() == nullptr, "no cha for final klass"); - if (DeoptC1 && UseCHA && !(ik->has_subklass() || ik->is_interface())) { + if (UseCHA && !(ik->has_subklass() || ik->is_interface())) { dependency_recorder()->assert_leaf_type(ik); return ik; } diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index 8658bebdaee..c11017fc442 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -1855,7 +1855,6 @@ void GraphBuilder::access_field(Bytecodes::Code code) { Dependencies* GraphBuilder::dependency_recorder() const { - assert(DeoptC1, "need debug information"); return compilation()->dependency_recorder(); } @@ -2001,7 +2000,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) { ciMethod* cha_monomorphic_target = nullptr; ciMethod* exact_target = nullptr; Value better_receiver = nullptr; - if (UseCHA && DeoptC1 && target->is_loaded() && + if (UseCHA && target->is_loaded() && !(// %%% FIXME: Are both of these relevant? target->is_method_handle_intrinsic() || target->is_compiled_lambda_form()) && @@ -2252,7 +2251,7 @@ bool GraphBuilder::direct_compare(ciKlass* k) { if (ik->is_final()) { return true; } else { - if (DeoptC1 && UseCHA && !(ik->has_subklass() || ik->is_interface())) { + if (UseCHA && !(ik->has_subklass() || ik->is_interface())) { // test class is leaf class dependency_recorder()->assert_leaf_type(ik); return true; diff --git a/src/hotspot/share/c1/c1_globals.hpp b/src/hotspot/share/c1/c1_globals.hpp index e3615ae88ad..755a1572e54 100644 --- a/src/hotspot/share/c1/c1_globals.hpp +++ b/src/hotspot/share/c1/c1_globals.hpp @@ -244,9 +244,6 @@ develop(bool, GenerateArrayStoreCheck, true, \ "Generates code for array store checks") \ \ - develop(bool, DeoptC1, true, \ - "Use deoptimization in C1") \ - \ develop(bool, PrintBailouts, false, \ "Print bailout and its reason") \ \ From 54fec2b98ba2197a588df37d805c3ad495fd0e61 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 24 Jun 2025 07:34:15 +0000 Subject: [PATCH 153/213] 8360220: Deprecate and obsolete ParallelRefProcBalancingEnabled Reviewed-by: kbarrett, tschatzl --- src/hotspot/share/gc/shared/gc_globals.hpp | 2 +- src/hotspot/share/runtime/arguments.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 903afd58b21..b15518ab225 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -203,7 +203,7 @@ "whenever possible") \ \ product(bool, ParallelRefProcBalancingEnabled, true, \ - "Enable balancing of reference processing queues") \ + "(Deprecated) Enable balancing of reference processing queues") \ \ product(size_t, ReferencesPerThread, 1000, EXPERIMENTAL, \ "Ergonomically start one thread for this amount of " \ diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index ef588b431e8..0d39fed52db 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -533,6 +533,7 @@ static SpecialFlag const special_jvm_flags[] = { { "UseCompressedClassPointers", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::undefined() }, #endif { "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, + { "ParallelRefProcBalancingEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, // --- Deprecated alias flags (see also aliased_jvm_flags) - sorted by obsolete_in then expired_in: { "CreateMinidumpOnCrash", JDK_Version::jdk(9), JDK_Version::undefined(), JDK_Version::undefined() }, From fdfc557878a7a2ec984002f38b871da5eec71217 Mon Sep 17 00:00:00 2001 From: David Beaumont Date: Tue, 24 Jun 2025 08:09:53 +0000 Subject: [PATCH 154/213] 8360131: Remove use of soon-to-be-removed APIs by CTW framework Reviewed-by: liach, thartmann --- .../tools/ctw/ClassPathJimageEntry.java | 69 ++++++++++++------- .../ctw/src/sun/hotspot/tools/ctw/Utils.java | 12 +++- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java index d6af006c138..56d611426ab 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJimageEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,13 +23,19 @@ package sun.hotspot.tools.ctw; -import jdk.internal.jimage.ImageLocation; -import jdk.internal.jimage.ImageReader; - import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.FileSystem; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; -import java.util.Arrays; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.spi.FileSystemProvider; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.stream.Stream; /** @@ -39,17 +45,21 @@ public class ClassPathJimageEntry extends PathHandler.PathEntry { @Override protected Stream classes() { - return Arrays.stream(reader.getEntryNames()) - .filter(name -> name.endsWith(".class")) - .filter(name -> !name.endsWith("module-info.class")) - .map(ClassPathJimageEntry::toFileName) - .map(Utils::fileNameToClassName); - } - - private static String toFileName(String name) { - final char nameSeparator = '/'; - assert name.charAt(0) == nameSeparator : name; - return name.substring(name.indexOf(nameSeparator, 1) + 1); + Path modulesRoot = jrtFileSystem.getPath("/modules"); + List classNames = new ArrayList<>(); + FileVisitor collectClassNames = new SimpleFileVisitor<>() { + @Override + public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { + classNames.add(Utils.fileNameToClassName(modulesRoot.relativize(path).toString())); + return FileVisitResult.CONTINUE; + } + }; + try { + Files.walkFileTree(modulesRoot, collectClassNames); + } catch (IOException e) { + throw new Error(e); + } + return classNames.stream(); } @Override @@ -60,7 +70,7 @@ protected String description() { @Override public void close() { try { - reader.close(); + jrtFileSystem.close(); } catch (IOException e) { throw new Error("error on closing reader for " + root + " : " + e.getMessage(), e); @@ -69,7 +79,7 @@ public void close() { } } - private final ImageReader reader; + private final FileSystem jrtFileSystem; public ClassPathJimageEntry(Path root) { super(root); @@ -77,7 +87,11 @@ public ClassPathJimageEntry(Path root) { throw new Error(root + " image file not found"); } try { - reader = ImageReader.open(root); + jrtFileSystem = FileSystemProvider.installedProviders().stream() + .filter(p -> "jrt".equals(p.getScheme())) + .findFirst() + .orElseThrow(() -> new Error("cannot find JRT filesystem for " + root)) + .newFileSystem(root, Map.of()); } catch (IOException e) { throw new Error("can not open " + root + " : " + e.getMessage(), e); } @@ -85,14 +99,19 @@ public ClassPathJimageEntry(Path root) { @Override protected byte[] findByteCode(String name) { - String resource = Utils.classNameToFileName(name); - for (String m : reader.getModuleNames()) { - ImageLocation location = reader.findLocation(m, resource); - if (location != null) { - return reader.getResource(location); + // Relative path to search for inside each /modules/ directory. + Path resourcePath = jrtFileSystem.getPath(Utils.classNameToFileName(name)); + Path modulesRoot = jrtFileSystem.getPath("/modules"); + try (DirectoryStream modules = Files.newDirectoryStream(modulesRoot)) { + for (Path module : modules) { + Path p = module.resolve(resourcePath); + if (Files.isRegularFile(p)) { + return Files.readAllBytes(p); + } } + } catch (IOException e) { + throw new RuntimeException(e); } return null; } - } diff --git a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java index 7c4c749ccce..ec24d4f186d 100644 --- a/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java +++ b/test/hotspot/jtreg/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -186,10 +186,10 @@ public static boolean isClassFile(String filename) { } /** - * Converts the filename to classname. + * Converts the {@code /}-separated filename to its corresponding class name. * * @param filename filename to convert - * @return corresponding classname + * @return corresponding class name * @throws AssertionError if filename isn't valid filename for class file - * {@link #isClassFile(String)} */ @@ -200,6 +200,12 @@ public static String fileNameToClassName(String filename) { .replace(nameSeparator, '.'); } + /** + * Converts a fully qualified class name to a {@code /}-separated filename. + * + * @param classname fully qualified class name to convert + * @return corresponding filename + */ public static String classNameToFileName(String classname) { return classname.replace('.', '/') .concat(CLASSFILE_EXT); From 116b8543b04bfcf542af0ba03ac547a744600b7c Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Tue, 24 Jun 2025 09:15:58 +0000 Subject: [PATCH 155/213] 8351983: HttpCookie Parser Incorrectly Handles Cookies with Expires Attribute Reviewed-by: dfuchs, vyazici --- .../share/classes/java/net/HttpCookie.java | 121 +++++++++++----- .../whitebox/MaxAgeExpiresDriver.java | 31 ++++ .../java.base/java/net/MaxAgeExpires.java | 137 ++++++++++++++++++ 3 files changed, 250 insertions(+), 39 deletions(-) create mode 100644 test/jdk/java/net/HttpCookie/whitebox/MaxAgeExpiresDriver.java create mode 100644 test/jdk/java/net/HttpCookie/whitebox/java.base/java/net/MaxAgeExpires.java diff --git a/src/java.base/share/classes/java/net/HttpCookie.java b/src/java.base/share/classes/java/net/HttpCookie.java index 871b885c085..3c633522bdf 100644 --- a/src/java.base/share/classes/java/net/HttpCookie.java +++ b/src/java.base/share/classes/java/net/HttpCookie.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,10 +51,12 @@ * http://www.ietf.org/rfc/rfc2965.txt * * - *

      HttpCookie class can accept all these 3 forms of syntax. + *

      HttpCookie class can accept all these 3 forms of syntax. This class also provides + * partial support for RFC 6265. * * @spec https://www.rfc-editor.org/info/rfc2109 RFC 2109: HTTP State Management Mechanism * @spec https://www.rfc-editor.org/info/rfc2965 RFC 2965: HTTP State Management Mechanism + * @spec https://www.rfc-editor.org/info/rfc6265 RFC 6265: HTTP State Management Mechanism * @author Edward Wang * @since 1.6 */ @@ -185,14 +187,14 @@ private HttpCookie(String name, String value, String header) { * if the header string is {@code null} */ public static List parse(String header) { - return parse(header, false); + return parse(header, false, -1L); } // Private version of parse() that will store the original header used to // create the cookie, in the cookie itself. This can be useful for filtering // Set-Cookie[2] headers, using the internal parsing logic defined in this - // class. - private static List parse(String header, boolean retainHeader) { + // class. Also, allows for testing by specifying the creation time. + static List parse(String header, boolean retainHeader, long currentTimeMillis) { int version = guessCookieVersion(header); @@ -209,7 +211,7 @@ private static List parse(String header, boolean retainHeader) { // so the parse logic is slightly different if (version == 0) { // Netscape draft cookie - HttpCookie cookie = parseInternal(header, retainHeader); + HttpCookie cookie = parseInternal(header, retainHeader, currentTimeMillis); cookie.setVersion(0); cookies.add(cookie); } else { @@ -218,7 +220,7 @@ private static List parse(String header, boolean retainHeader) { // it'll separate them with comma List cookieStrings = splitMultiCookies(header); for (String cookieStr : cookieStrings) { - HttpCookie cookie = parseInternal(cookieStr, retainHeader); + HttpCookie cookie = parseInternal(cookieStr, retainHeader, currentTimeMillis); cookie.setVersion(1); cookies.add(cookie); } @@ -230,12 +232,19 @@ private static List parse(String header, boolean retainHeader) { // ---------------- Public operations -------------- /** - * Reports whether this HTTP cookie has expired or not. + * Reports whether this HTTP cookie has expired or not. This is + * based on whether {@link #getMaxAge()} seconds have elapsed since + * this object was created. * * @return {@code true} to indicate this HTTP cookie has expired; * otherwise, {@code false} */ public boolean hasExpired() { + return hasExpired(System.currentTimeMillis()); + } + + // PP for testing + boolean hasExpired(long currentTimeMillis) { if (maxAge == 0) return true; // if not specify max-age, this cookie should be @@ -243,7 +252,7 @@ public boolean hasExpired() { // it is not expired. if (maxAge < 0) return false; - long deltaSecond = (System.currentTimeMillis() - whenCreated) / 1000; + long deltaSecond = (currentTimeMillis - whenCreated) / 1000; if (deltaSecond > maxAge) return true; else @@ -411,8 +420,19 @@ public void setMaxAge(long expiry) { } /** - * Returns the maximum age of the cookie, specified in seconds. By default, - * {@code -1} indicating the cookie will persist until browser shutdown. + * Returns the maximum age of the cookie, specified in seconds from the time + * the object was created. By default, {@code -1} indicating the cookie will + * persist until browser shutdown. + * + * The value of this attribute is determined by the following steps, in line + * with RFC 6265: + * + *

      1. If {@link #setMaxAge(long)} was called, return the value set.
      2. + *
      3. If previous step failed, and a {@code Max-Age} attribute was parsed + * then return that value.
      4. + *
      5. If previous step failed, and an {@code Expires} attribute was parsed + * then the maxAge calculated at parsing time from that date, is returned
      6. + *
      7. If previous step failed, then return {@code -1}.
      * * @return an integer specifying the maximum age of the cookie in seconds * @@ -810,10 +830,13 @@ private static boolean isToken(String value) { * if header string violates the cookie specification */ private static HttpCookie parseInternal(String header, - boolean retainHeader) + boolean retainHeader, + long currentTimeMillis) { HttpCookie cookie = null; String namevaluePair = null; + if (currentTimeMillis == -1L) + currentTimeMillis = System.currentTimeMillis(); StringTokenizer tokenizer = new StringTokenizer(header, ";"); @@ -828,10 +851,11 @@ private static HttpCookie parseInternal(String header, if (retainHeader) cookie = new HttpCookie(name, stripOffSurroundingQuote(value), - header); + header, currentTimeMillis); else cookie = new HttpCookie(name, - stripOffSurroundingQuote(value)); + stripOffSurroundingQuote(value), + null, currentTimeMillis); } else { // no "=" in name-value pair; it's an error throw new IllegalArgumentException("Invalid cookie name-value pair"); @@ -840,6 +864,10 @@ private static HttpCookie parseInternal(String header, throw new IllegalArgumentException("Empty cookie header string"); } + // Attributes that require special handling + String expiresValue = null; + String maxAgeValue = null; + // remaining name-value pairs are cookie's attributes while (tokenizer.hasMoreTokens()) { namevaluePair = tokenizer.nextToken(); @@ -852,10 +880,19 @@ private static HttpCookie parseInternal(String header, name = namevaluePair.trim(); value = null; } + if (name.equalsIgnoreCase("max-age") && maxAgeValue == null) { + maxAgeValue = value; + continue; + } + if (name.equalsIgnoreCase("expires") && expiresValue == null) { + expiresValue = value; + continue; + } // assign attribute to cookie assignAttribute(cookie, name, value); } + assignMaxAgeAttribute(cookie, expiresValue, maxAgeValue); return cookie; } @@ -903,20 +940,6 @@ public void assign(HttpCookie cookie, cookie.setDomain(attrValue); } }); - assignors.put("max-age", new CookieAttributeAssignor(){ - public void assign(HttpCookie cookie, - String attrName, - String attrValue) { - try { - long maxage = Long.parseLong(attrValue); - if (cookie.getMaxAge() == MAX_AGE_UNSPECIFIED) - cookie.setMaxAge(maxage); - } catch (NumberFormatException ignored) { - throw new IllegalArgumentException( - "Illegal cookie max-age attribute"); - } - } - }); assignors.put("path", new CookieAttributeAssignor(){ public void assign(HttpCookie cookie, String attrName, @@ -959,17 +982,37 @@ public void assign(HttpCookie cookie, } } }); - assignors.put("expires", new CookieAttributeAssignor(){ // Netscape only - public void assign(HttpCookie cookie, - String attrName, - String attrValue) { - if (cookie.getMaxAge() == MAX_AGE_UNSPECIFIED) { - long delta = cookie.expiryDate2DeltaSeconds(attrValue); - cookie.setMaxAge(delta > 0 ? delta : 0); - } - } - }); } + + private static void assignMaxAgeAttribute(HttpCookie cookie, + String expiresValue, + String maxAgeValue) + { + if (cookie.getMaxAge() != MAX_AGE_UNSPECIFIED) + return; + if (expiresValue == null && maxAgeValue == null) + return; + + // strip off the surrounding "-sign if there's any + expiresValue = stripOffSurroundingQuote(expiresValue); + maxAgeValue = stripOffSurroundingQuote(maxAgeValue); + + try { + if (maxAgeValue != null) { + long maxAge = Long.parseLong(maxAgeValue); + cookie.maxAge = maxAge; + return; + } + } catch (NumberFormatException ignored) {} + + try { + if (expiresValue != null) { + long delta = cookie.expiryDate2DeltaSeconds(expiresValue); + cookie.maxAge = (delta > 0 ? delta : 0); + } + } catch (NumberFormatException ignored) {} + } + private static void assignAttribute(HttpCookie cookie, String attrName, String attrValue) @@ -989,7 +1032,7 @@ private static void assignAttribute(HttpCookie cookie, SharedSecrets.setJavaNetHttpCookieAccess( new JavaNetHttpCookieAccess() { public List parse(String header) { - return HttpCookie.parse(header, true); + return HttpCookie.parse(header, true, -1L); } public String header(HttpCookie cookie) { diff --git a/test/jdk/java/net/HttpCookie/whitebox/MaxAgeExpiresDriver.java b/test/jdk/java/net/HttpCookie/whitebox/MaxAgeExpiresDriver.java new file mode 100644 index 00000000000..7f535fa0c23 --- /dev/null +++ b/test/jdk/java/net/HttpCookie/whitebox/MaxAgeExpiresDriver.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8351983 + * @summary HttpCookie Parser Incorrectly Handles Cookies with Expires Attribute + * @run testng java.base/java.net.MaxAgeExpires + */ +public class MaxAgeExpiresDriver { +} \ No newline at end of file diff --git a/test/jdk/java/net/HttpCookie/whitebox/java.base/java/net/MaxAgeExpires.java b/test/jdk/java/net/HttpCookie/whitebox/java.base/java/net/MaxAgeExpires.java new file mode 100644 index 00000000000..5c4f8f66b3d --- /dev/null +++ b/test/jdk/java/net/HttpCookie/whitebox/java.base/java/net/MaxAgeExpires.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net; + +import java.time.*; +import java.time.format.DateTimeFormatter; +import java.util.*; +import org.testng.Assert; +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; + +public class MaxAgeExpires { + + static final DateTimeFormatter dtFormatter = + DateTimeFormatter.RFC_1123_DATE_TIME; + + static final String NOW_PLUS_500_SEC = + dtFormatter.format(ZonedDateTime.ofInstant(Instant.now() + .plusSeconds(500), ZoneId.of("UTC"))); + + // Test dates 1 minute apart + static final String DT1 = "Mon, 01 Jan 2024 01:00:00 GMT"; + static final String DT2 = "Mon, 01 Jan 2024 01:01:00 GMT"; + static final String DT3 = "Mon, 01 Jan 2024 01:02:00 GMT"; + + static final String FAR_FUTURE = "Mon, 01 Jan 4024 01:02:00 GMT"; + + static final ZonedDateTime zdt1 = ZonedDateTime.parse(DT1, dtFormatter); + static final ZonedDateTime zdt2 = ZonedDateTime.parse(DT2, dtFormatter); + static final ZonedDateTime zdt3 = ZonedDateTime.parse(DT3, dtFormatter); + + static long zdtToMillis(ZonedDateTime zdt) { + return zdt.toInstant().getEpochSecond() * 1000; // always exact seconds + } + + @DataProvider(name = "testData") + public Object[][] testData() { + return new Object[][] { + // Date string in past. But checking based on current time. + {-1L, -1L, -1L, DT1, 0, true}, + {-1L, -1L, 1000, DT1, 1000, false}, + {-1L, -1L, 0, DT1, 0, true}, + {-1L, -1L, 1000, NOW_PLUS_500_SEC, 1000, false}, + + // Far in the future. Just check hasExpired() not the exact maxAge + {-1L, -1L, -1L, FAR_FUTURE, -1L, false}, + + // Tests using fixed creation and verification dates + // (independent of current time) + // expires= + // maxAge= | + // create time expiry check time | |expected maxAge + // | | | | | hasExpired() + // | | | | | | expected + {zdtToMillis(zdt1), zdtToMillis(zdt3), -1L, DT2, 60, true}, + {zdtToMillis(zdt1), zdtToMillis(zdt3), 20, DT2, 20, true}, + {zdtToMillis(zdt1), zdtToMillis(zdt2), 40, DT3, 40, true}, + {zdtToMillis(zdt1), zdtToMillis(zdt2), -1L, DT3,120, false} + + }; + }; + + + @Test(dataProvider = "testData") + public void test1(long creationInstant, // if -1, then current time is used + long expiryCheckInstant, // if -1 then current time is used + long maxAge, // if -1, then not included in String + String expires, // if null, then not included in String + long expectedAge, // expected return value from getMaxAge() + boolean hasExpired) // expected return value from hasExpired() + throws Exception + { + StringBuilder sb = new StringBuilder(); + sb.append("Set-Cookie: name=value"); + if (expires != null) + sb.append("; expires=" + expires); + if (maxAge != -1) + sb.append("; max-age=" + Long.toString(maxAge)); + + String s = sb.toString(); + System.out.println(s); + HttpCookie cookie; + if (creationInstant == -1) + cookie = HttpCookie.parse(s).get(0); + else + cookie = HttpCookie.parse(s, false, creationInstant).get(0); + + if (expectedAge != -1 && cookie.getMaxAge() != expectedAge) { + System.out.println("getMaxAge returned " + cookie.getMaxAge()); + System.out.println("expectedAge was " + expectedAge); + throw new RuntimeException("Test failed: wrong age"); + } + + boolean expired = expiryCheckInstant == -1 + ? cookie.hasExpired() + : cookie.hasExpired(expiryCheckInstant); + + if (expired != hasExpired) { + System.out.println("cookie.hasExpired() returned " + expired); + System.out.println("hasExpired was " + hasExpired); + System.out.println("getMaxAge() returned " + cookie.getMaxAge()); + throw new RuntimeException("Test failed: wrong hasExpired"); + } + } + + @Test + public void test2() { + // Miscellaneous tests that setMaxAge() overrides whatever was set already + HttpCookie cookie = HttpCookie.parse("Set-Cookie: name=value; max-age=100").get(0); + Assert.assertEquals(cookie.getMaxAge(), 100); + cookie.setMaxAge(200); + Assert.assertEquals(cookie.getMaxAge(), 200); + cookie.setMaxAge(-2); + Assert.assertEquals(cookie.getMaxAge(), -2); + } +} From a3609ba5ac6a5531d905cdd136eea72706f9a028 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 24 Jun 2025 10:34:14 +0000 Subject: [PATCH 156/213] 8360324: Parallel: Remove unused local variable in MutableNUMASpace::set_top Reviewed-by: tschatzl --- src/hotspot/share/gc/parallel/mutableNUMASpace.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index ede1c570ece..0375e969586 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -489,7 +489,6 @@ void MutableNUMASpace::set_top(HeapWord* value) { for (int i = 0; i < lgrp_spaces()->length();) { LGRPSpace *ls = lgrp_spaces()->at(i); MutableSpace *s = ls->space(); - HeapWord *top = MAX2(align_down(s->top(), page_size()), s->bottom()); if (s->contains(value)) { // Check if setting the chunk's top to a given value would create a hole less than From f5201ac117fa66638f36cec3bc5f5059b37f2860 Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Tue, 24 Jun 2025 11:17:48 +0000 Subject: [PATCH 157/213] 8359959: Test runtime/NMT/VirtualAllocTestType.java failed: '\\[0x[0]*7f7dc4043000 - 0x[0]*7f7dc4083000\\] reserved 256KB for Test' missing from stdout/stderr Reviewed-by: jsjolen, dholmes --- test/hotspot/jtreg/ProblemList.txt | 1 - .../runtime/NMT/VirtualAllocTestType.java | 27 ++++++++++++++----- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index f41d8fb64ca..40db325896b 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -112,7 +112,6 @@ runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/NMT/VirtualAllocCommitMerge.java 8309698 linux-s390x -runtime/NMT/VirtualAllocTestType.java 8359959 generic-all applications/jcstress/copy.java 8229852 linux-all diff --git a/test/hotspot/jtreg/runtime/NMT/VirtualAllocTestType.java b/test/hotspot/jtreg/runtime/NMT/VirtualAllocTestType.java index f4321e80b22..0ac7d297e38 100644 --- a/test/hotspot/jtreg/runtime/NMT/VirtualAllocTestType.java +++ b/test/hotspot/jtreg/runtime/NMT/VirtualAllocTestType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,12 +61,27 @@ public static void main(String args[]) throws Exception { addr2 = wb.NMTReserveMemory(reserveSize); info = "reserve 2: addr2=" + addr2; - // If the second mapping happens to be adjacent to the first mapping, reserve another mapping and release the second mapping; for - // this test, we want to see two disjunct mappings. - if (addr2 == addr1 + reserveSize) { + // For this test, we want to see two disjunct mappings. + if ((addr2 == addr1 + reserveSize) || (addr2 == addr1 - reserveSize)) { + // <---r1---><---r2--->...<---tmp---> + // <---tmp--->...<---r1---><---r2---> + // + // Reserve a new region and find whether r1 or r2 to be released. long tmp = wb.NMTReserveMemory(reserveSize); - wb.NMTReleaseMemory(addr2, reserveSize); - addr2 = tmp; + long r1 = addr1 < addr2 ? addr1 : addr2; + long r2 = addr1 > addr2 ? addr1 : addr2; + long tmp_end = tmp + reserveSize; + long r1_end = r1 + reserveSize; + long r2_end = r2 + reserveSize; + if (tmp >= r2_end) { + wb.NMTReleaseMemory(r2, reserveSize); + addr1 = r1; + addr2 = tmp; + } else if (tmp_end <= r1) { + wb.NMTReleaseMemory(r1, reserveSize); + addr1 = tmp; + addr2 = r2; + } } output = NMTTestUtils.startJcmdVMNativeMemoryDetail(); From 28e96e333b61dfe60a84a48ff59bdf10c529f8be Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 24 Jun 2025 12:31:04 +0000 Subject: [PATCH 158/213] 8359920: Use names for frame types in stackmaps Reviewed-by: dholmes, jsjolen, matsaave, sspitsyn --- src/hotspot/share/classfile/stackMapTable.cpp | 20 +++++++------- src/hotspot/share/classfile/stackMapTable.hpp | 17 +++++++++--- .../share/prims/jvmtiRedefineClasses.cpp | 27 +++++++++++-------- 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/src/hotspot/share/classfile/stackMapTable.cpp b/src/hotspot/share/classfile/stackMapTable.cpp index 1ed72e998fb..9e02956aceb 100644 --- a/src/hotspot/share/classfile/stackMapTable.cpp +++ b/src/hotspot/share/classfile/stackMapTable.cpp @@ -244,7 +244,7 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { int offset; VerificationType* locals = nullptr; u1 frame_type = _stream->get_u1(CHECK_NULL); - if (frame_type < 64) { + if (frame_type <= SAME_FRAME_END) { // same_frame if (_first) { offset = frame_type; @@ -266,17 +266,17 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { _first = false; return frame; } - if (frame_type < 128) { + if (frame_type <= SAME_LOCALS_1_STACK_ITEM_FRAME_END) { // same_locals_1_stack_item_frame if (_first) { - offset = frame_type - 64; + offset = frame_type - SAME_LOCALS_1_STACK_ITEM_FRAME_START; // Can't share the locals array since that is updated by the verifier. if (_prev_frame->locals_size() > 0) { locals = NEW_RESOURCE_ARRAY_IN_THREAD( THREAD, VerificationType, _prev_frame->locals_size()); } } else { - offset = _prev_frame->offset() + frame_type - 63; + offset = _prev_frame->offset() + frame_type - (SAME_LOCALS_1_STACK_ITEM_FRAME_START - 1); locals = _prev_frame->locals(); } VerificationType* stack = NEW_RESOURCE_ARRAY_IN_THREAD( @@ -340,13 +340,14 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { return frame; } - if (frame_type <= SAME_EXTENDED) { + if (frame_type <= SAME_FRAME_EXTENDED) { // chop_frame or same_frame_extended locals = _prev_frame->locals(); int length = _prev_frame->locals_size(); - int chops = SAME_EXTENDED - frame_type; + int chops = SAME_FRAME_EXTENDED - frame_type; int new_length = length; u1 flags = _prev_frame->flags(); + assert(chops == 0 || (frame_type >= CHOP_FRAME_START && frame_type <= CHOP_FRAME_END), "should be"); if (chops != 0) { new_length = chop(locals, length, chops); check_verification_type_array_size( @@ -380,9 +381,10 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { } _first = false; return frame; - } else if (frame_type < SAME_EXTENDED + 4) { + } else if (frame_type <= APPEND_FRAME_END) { // append_frame - int appends = frame_type - SAME_EXTENDED; + assert(frame_type >= APPEND_FRAME_START && frame_type <= APPEND_FRAME_END, "should be"); + int appends = frame_type - APPEND_FRAME_START + 1; int real_length = _prev_frame->locals_size(); int new_length = real_length + appends*2; locals = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, VerificationType, new_length); @@ -412,7 +414,7 @@ StackMapFrame* StackMapReader::next_helper(TRAPS) { _first = false; return frame; } - if (frame_type == FULL) { + if (frame_type == FULL_FRAME) { // full_frame u1 flags = 0; u2 locals_size = _stream->get_u2(CHECK_NULL); diff --git a/src/hotspot/share/classfile/stackMapTable.hpp b/src/hotspot/share/classfile/stackMapTable.hpp index cc4202f3280..6d4c0ce36c0 100644 --- a/src/hotspot/share/classfile/stackMapTable.hpp +++ b/src/hotspot/share/classfile/stackMapTable.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,6 +106,7 @@ class StackMapStream : StackObj { }; class StackMapReader : StackObj { + friend class VM_RedefineClasses; private: // information about the class and method constantPoolHandle _cp; @@ -148,9 +149,19 @@ class StackMapReader : StackObj { } enum { + SAME_FRAME_START = 0, + SAME_FRAME_END = 63, + SAME_LOCALS_1_STACK_ITEM_FRAME_START = 64, + SAME_LOCALS_1_STACK_ITEM_FRAME_END = 127, + RESERVED_START = 128, + RESERVED_END = 246, SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247, - SAME_EXTENDED = 251, - FULL = 255 + CHOP_FRAME_START = 248, + CHOP_FRAME_END = 250, + SAME_FRAME_EXTENDED = 251, + APPEND_FRAME_START = 252, + APPEND_FRAME_END = 254, + FULL_FRAME = 255 }; public: diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index ec4a6cd8c7f..b7abacbe5b3 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -29,6 +29,7 @@ #include "classfile/classLoadInfo.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/metadataOnStackMark.hpp" +#include "classfile/stackMapTable.hpp" #include "classfile/symbolTable.hpp" #include "classfile/klassFactory.hpp" #include "classfile/verifier.hpp" @@ -3267,7 +3268,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_stack_map_table( // same_frame { // u1 frame_type = SAME; /* 0-63 */ // } - if (frame_type <= 63) { + if (frame_type <= StackMapReader::SAME_FRAME_END) { // nothing more to do for same_frame } @@ -3275,13 +3276,15 @@ void VM_RedefineClasses::rewrite_cp_refs_in_stack_map_table( // u1 frame_type = SAME_LOCALS_1_STACK_ITEM; /* 64-127 */ // verification_type_info stack[1]; // } - else if (frame_type >= 64 && frame_type <= 127) { + else if (frame_type >= StackMapReader::SAME_LOCALS_1_STACK_ITEM_FRAME_START && + frame_type <= StackMapReader::SAME_LOCALS_1_STACK_ITEM_FRAME_END) { rewrite_cp_refs_in_verification_type_info(stackmap_p, stackmap_end, calc_number_of_entries, frame_type); } // reserved for future use - else if (frame_type >= 128 && frame_type <= 246) { + else if (frame_type >= StackMapReader::RESERVED_START && + frame_type <= StackMapReader::RESERVED_END) { // nothing more to do for reserved frame_types } @@ -3290,7 +3293,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_stack_map_table( // u2 offset_delta; // verification_type_info stack[1]; // } - else if (frame_type == 247) { + else if (frame_type == StackMapReader::SAME_LOCALS_1_STACK_ITEM_EXTENDED) { stackmap_p += 2; rewrite_cp_refs_in_verification_type_info(stackmap_p, stackmap_end, calc_number_of_entries, frame_type); @@ -3300,28 +3303,30 @@ void VM_RedefineClasses::rewrite_cp_refs_in_stack_map_table( // u1 frame_type = CHOP; /* 248-250 */ // u2 offset_delta; // } - else if (frame_type >= 248 && frame_type <= 250) { + else if (frame_type >= StackMapReader::CHOP_FRAME_START && + frame_type <= StackMapReader::CHOP_FRAME_END) { stackmap_p += 2; } // same_frame_extended { - // u1 frame_type = SAME_FRAME_EXTENDED; /* 251*/ + // u1 frame_type = SAME_EXTENDED; /* 251 */ // u2 offset_delta; // } - else if (frame_type == 251) { + else if (frame_type == StackMapReader::SAME_FRAME_EXTENDED) { stackmap_p += 2; } // append_frame { // u1 frame_type = APPEND; /* 252-254 */ // u2 offset_delta; - // verification_type_info locals[frame_type - 251]; + // verification_type_info locals[frame_type - SAME_EXTENDED]; // } - else if (frame_type >= 252 && frame_type <= 254) { + else if (frame_type >= StackMapReader::APPEND_FRAME_START && + frame_type <= StackMapReader::APPEND_FRAME_END) { assert(stackmap_p + 2 <= stackmap_end, "no room for offset_delta"); stackmap_p += 2; - u1 len = frame_type - 251; + u1 len = frame_type - StackMapReader::APPEND_FRAME_START + 1; for (u1 i = 0; i < len; i++) { rewrite_cp_refs_in_verification_type_info(stackmap_p, stackmap_end, calc_number_of_entries, frame_type); @@ -3336,7 +3341,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_stack_map_table( // u2 number_of_stack_items; // verification_type_info stack[number_of_stack_items]; // } - else if (frame_type == 255) { + else if (frame_type == StackMapReader::FULL_FRAME) { assert(stackmap_p + 2 + 2 <= stackmap_end, "no room for smallest full_frame"); stackmap_p += 2; From 0514cee6c884b6d31735551b8a3ce7a2be661094 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 24 Jun 2025 14:27:47 +0000 Subject: [PATCH 159/213] 8360177: ParallelArguments::initialize has incorrect format string Reviewed-by: tschatzl, sangheki --- src/hotspot/share/gc/parallel/parallelArguments.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/parallel/parallelArguments.cpp b/src/hotspot/share/gc/parallel/parallelArguments.cpp index cae6f9a93d5..dcd5b6ae454 100644 --- a/src/hotspot/share/gc/parallel/parallelArguments.cpp +++ b/src/hotspot/share/gc/parallel/parallelArguments.cpp @@ -70,7 +70,7 @@ void ParallelArguments::initialize() { if (FLAG_IS_CMDLINE(InitialSurvivorRatio)) { if (FLAG_IS_CMDLINE(MinSurvivorRatio)) { jio_fprintf(defaultStream::error_stream(), - "Inconsistent MinSurvivorRatio vs InitialSurvivorRatio: %d vs %d\n", MinSurvivorRatio, InitialSurvivorRatio); + "Inconsistent MinSurvivorRatio vs InitialSurvivorRatio: %zu vs %zu\n", MinSurvivorRatio, InitialSurvivorRatio); } FLAG_SET_DEFAULT(MinSurvivorRatio, InitialSurvivorRatio); } else { From 54acadbe668f6feced6eb9c28bcf46d1b3986eec Mon Sep 17 00:00:00 2001 From: Gautham Krishnan Date: Tue, 24 Jun 2025 14:53:14 +0000 Subject: [PATCH 160/213] 8294226: Document missing UnsupportedTemporalTypeException Reviewed-by: rriggs, naoto --- .../share/classes/java/time/chrono/ChronoLocalDate.java | 1 + .../share/classes/java/time/chrono/ChronoLocalDateTime.java | 6 +++++- .../share/classes/java/time/chrono/ChronoZonedDateTime.java | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java b/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java index 3aae065715a..59416403003 100644 --- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java +++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDate.java @@ -455,6 +455,7 @@ default ChronoLocalDate plus(TemporalAmount amount) { /** * {@inheritDoc} * @throws DateTimeException {@inheritDoc} + * @throws UnsupportedTemporalTypeException {@inheritDoc} * @throws ArithmeticException {@inheritDoc} */ @Override diff --git a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java index 73b3a1e8a88..8ed2f910525 100644 --- a/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java +++ b/src/java.base/share/classes/java/time/chrono/ChronoLocalDateTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,6 +84,7 @@ import java.time.temporal.TemporalQueries; import java.time.temporal.TemporalQuery; import java.time.temporal.TemporalUnit; +import java.time.temporal.UnsupportedTemporalTypeException; import java.time.zone.ZoneRules; import java.util.Comparator; import java.util.Objects; @@ -276,6 +277,7 @@ default ChronoLocalDateTime with(TemporalAdjuster adjuster) { /** * {@inheritDoc} * @throws DateTimeException {@inheritDoc} + * @throws UnsupportedTemporalTypeException {@inheritDoc} * @throws ArithmeticException {@inheritDoc} */ @Override @@ -294,6 +296,7 @@ default ChronoLocalDateTime plus(TemporalAmount amount) { /** * {@inheritDoc} * @throws DateTimeException {@inheritDoc} + * @throws UnsupportedTemporalTypeException {@inheritDoc} * @throws ArithmeticException {@inheritDoc} */ @Override @@ -312,6 +315,7 @@ default ChronoLocalDateTime minus(TemporalAmount amount) { /** * {@inheritDoc} * @throws DateTimeException {@inheritDoc} + * @throws UnsupportedTemporalTypeException {@inheritDoc} * @throws ArithmeticException {@inheritDoc} */ @Override diff --git a/src/java.base/share/classes/java/time/chrono/ChronoZonedDateTime.java b/src/java.base/share/classes/java/time/chrono/ChronoZonedDateTime.java index 8892bc471b6..57f0bac4008 100644 --- a/src/java.base/share/classes/java/time/chrono/ChronoZonedDateTime.java +++ b/src/java.base/share/classes/java/time/chrono/ChronoZonedDateTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -422,6 +422,7 @@ default ChronoZonedDateTime with(TemporalAdjuster adjuster) { /** * {@inheritDoc} * @throws DateTimeException {@inheritDoc} + * @throws UnsupportedTemporalTypeException {@inheritDoc} * @throws ArithmeticException {@inheritDoc} */ @Override @@ -440,6 +441,7 @@ default ChronoZonedDateTime plus(TemporalAmount amount) { /** * {@inheritDoc} * @throws DateTimeException {@inheritDoc} + * @throws UnsupportedTemporalTypeException {@inheritDoc} * @throws ArithmeticException {@inheritDoc} */ @Override @@ -458,6 +460,7 @@ default ChronoZonedDateTime minus(TemporalAmount amount) { /** * {@inheritDoc} * @throws DateTimeException {@inheritDoc} + * @throws UnsupportedTemporalTypeException {@inheritDoc} * @throws ArithmeticException {@inheritDoc} */ @Override From 5c1f77fab1f56e470157d8680310417924abb298 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 24 Jun 2025 15:05:40 +0000 Subject: [PATCH 161/213] 8360201: JFR: Initialize JfrThreadLocal::_sampling_critical_section Reviewed-by: zgu, mgronlun --- src/hotspot/share/jfr/support/jfrThreadLocal.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 4b805a98a32..67d311e2a6e 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -79,7 +79,8 @@ JfrThreadLocal::JfrThreadLocal() : _enqueued_requests(false), _vthread(false), _notified(false), - _dead(false) + _dead(false), + _sampling_critical_section(false) #ifdef LINUX ,_cpu_timer(nullptr), _cpu_time_jfr_locked(UNLOCKED), From 2af869b193017bbd8bec4cfef9f0870de6ec1285 Mon Sep 17 00:00:00 2001 From: Artur Barashev Date: Tue, 24 Jun 2025 15:32:13 +0000 Subject: [PATCH 162/213] 8156715: TrustStoreManager does not buffer keystore input stream Reviewed-by: ascarpino --- .../classes/sun/security/ssl/TrustStoreManager.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/TrustStoreManager.java b/src/java.base/share/classes/sun/security/ssl/TrustStoreManager.java index 82dc82362ca..e2c353847c7 100644 --- a/src/java.base/share/classes/sun/security/ssl/TrustStoreManager.java +++ b/src/java.base/share/classes/sun/security/ssl/TrustStoreManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -376,9 +376,10 @@ private static KeyStore loadKeyStore( } if (!"NONE".equals(descriptor.storeName)) { - try (FileInputStream fis = - new FileInputStream(descriptor.storeFile)) { - ks.load(fis, password); + try (BufferedInputStream bis = + new BufferedInputStream( + new FileInputStream(descriptor.storeFile))) { + ks.load(bis, password); } catch (FileNotFoundException fnfe) { // No file available, no KeyStore available. if (SSLLogger.isOn && SSLLogger.isOn("trustmanager")) { From 9a726df3731a22bdd4e768d83835aba9240967d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Tue, 24 Jun 2025 15:48:31 +0000 Subject: [PATCH 163/213] 8359024: Accessibility bugs in API documentation Reviewed-by: vyazici, liach --- .../internal/doclets/formats/html/Table.java | 6 +-- .../formats/html/resources/stylesheet.css | 10 ++-- .../doclet/testNewApiList/TestNewApiList.java | 52 +++++++++---------- .../doclet/testPreview/TestPreview.java | 8 +-- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java index 6ba40145e8f..572d489057e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/Table.java @@ -385,12 +385,12 @@ private Content toContent() { table.add(getTableBody()); main.add(table); } else { - var tablist = HtmlTree.DIV(HtmlStyles.tableTabs) - .put(HtmlAttr.ROLE, "tablist") - .put(HtmlAttr.ARIA_ORIENTATION, "horizontal"); + var tablist = HtmlTree.DIV(HtmlStyles.tableTabs); HtmlId defaultTabId = HtmlIds.forTab(id, 0); if (renderTabs) { + tablist.put(HtmlAttr.ROLE, "tablist") + .put(HtmlAttr.ARIA_ORIENTATION, "horizontal"); tablist.add(createTab(defaultTabId, HtmlStyles.activeTableTab, true, defaultTab)); for (var tab : tabs) { if (occurringTabs.contains(tab)) { 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 2c10cb3bc6f..f7994c7f7ed 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 @@ -29,8 +29,8 @@ --block-line-height: 1.5; --code-line-height: 1.6; /* Text colors for body and block elements */ - --body-text-color: #282828; - --block-text-color: #282828; + --body-text-color: #181818; + --block-text-color: #181818; /* Background colors for various elements */ --body-background-color: #ffffff; --section-background-color: var(--body-background-color); @@ -656,14 +656,14 @@ ul.preview-feature-list input { .class-use-page .caption span, .package-use-page .caption span, .constants-summary-page .caption span, -.inherited-list.expanded h3 { +.inherited-list h3 { background-color: var(--subnav-background-color); color: var(--block-text-color); } .caption a:link, .caption a:visited, -.inherited-list.expanded h3 a:link, -.inherited-list.expanded h3 a:visited { +.inherited-list h3 a:link, +.inherited-list h3 a:visited { color:var(--subnav-link-color); } div.table-tabs { diff --git a/test/langtools/jdk/javadoc/doclet/testNewApiList/TestNewApiList.java b/test/langtools/jdk/javadoc/doclet/testNewApiList/TestNewApiList.java index 1d3dda52fc4..956bae37435 100644 --- a/test/langtools/jdk/javadoc/doclet/testNewApiList/TestNewApiList.java +++ b/test/langtools/jdk/javadoc/doclet/testNewApiList/TestNewApiList.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8263468 8269401 8268422 8287524 8325874 8331873 8345555 + * @bug 8263468 8269401 8268422 8287524 8325874 8331873 8345555 8359024 * @summary New page for "recent" new API * @library ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -126,7 +126,7 @@ private void checkMultiReleaseNewElements() { checkOutput("new-list.html", true, """
      -
      +
      New Modules
      @@ -142,7 +142,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Packages
      @@ -158,7 +158,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Interfaces
      @@ -174,7 +174,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Classes
      @@ -190,7 +190,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Enum Classes
      @@ -206,7 +206,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Exception Classes
      @@ -228,7 +228,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Record Classes
      @@ -244,7 +244,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Annotation Interfaces
      @@ -259,7 +259,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Fields
      @@ -293,7 +293,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Methods
      @@ -359,7 +359,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Constructors
      @@ -394,7 +394,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Enum Constants
      @@ -428,7 +428,7 @@ private void checkMultiReleaseNewElements() {
      """, """
      -
      +
      New Annotation Interface Elements
      @@ -456,7 +456,7 @@ private void checkMultiReleaseDeprecatedElements() { checkOutput("deprecated-list.html", true, """
      -
      +
      Terminally Deprecated Elements
      @@ -471,7 +471,7 @@ private void checkMultiReleaseDeprecatedElements() {
      """, """
      -
      +
      Deprecated Methods
      @@ -486,7 +486,7 @@ private void checkMultiReleaseDeprecatedElements() {
      """, """
      -
      +
      Deprecated Constructors
      @@ -501,7 +501,7 @@ private void checkMultiReleaseDeprecatedElements() {
      """, """
      -
      +
      Deprecated Enum Constants
      @@ -516,7 +516,7 @@ private void checkMultiReleaseDeprecatedElements() {
      """, """
      -
      +
      Deprecated Annotation Interface Elements
      @@ -606,7 +606,7 @@ private void checkSingleReleaseDeprecatedElements() {
    """, """
    -
    +
    Terminally Deprecated Elements
    @@ -621,7 +621,7 @@ private void checkSingleReleaseDeprecatedElements() {
    """, """
    -
    +
    Deprecated Methods
    @@ -636,7 +636,7 @@ private void checkSingleReleaseDeprecatedElements() {
    """, """
    -
    +
    Deprecated Constructors
    @@ -680,7 +680,7 @@ private void checkPackageNewElements() { checkOutput("new-list.html", true, """
    -
    +
    New Classes
    @@ -696,7 +696,7 @@ private void checkPackageNewElements() {
    """, """
    -
    +
    New Fields
    @@ -712,7 +712,7 @@ private void checkPackageNewElements() {
    """, """
    -
    +
    New Methods
    @@ -741,7 +741,7 @@ private void checkPackageNewElements() {
    """, """
    -
    +
    New Constructors
    diff --git a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java index 07e5b69c463..b883de1920b 100644 --- a/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java +++ b/test/langtools/jdk/javadoc/doclet/testPreview/TestPreview.java @@ -24,7 +24,7 @@ /* * @test * @bug 8250768 8261976 8277300 8282452 8287597 8325325 8325874 8297879 - * 8331947 8281533 8343239 8318416 8346109 + * 8331947 8281533 8343239 8318416 8346109 8359024 * @summary test generated docs for items declared using preview * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -104,7 +104,7 @@ public void testPreviewAPIJavadoc() { """, """
    -
    +
    Packages
    @@ -122,7 +122,7 @@ public void testPreviewAPIJavadoc() { """, """
    -
    +
    Record Classes
    @@ -139,7 +139,7 @@ public void testPreviewAPIJavadoc() { """, """
    -
    +
    Methods
    From f8de5bc5827742dd60b8f8f4a0d3625c370af15b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Tue, 24 Jun 2025 15:50:51 +0000 Subject: [PATCH 164/213] 8328848: Inaccuracy in the documentation of the -group option Reviewed-by: liach --- .../doclets/formats/html/resources/standard.properties | 2 +- src/jdk.javadoc/share/man/javadoc.md | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties index 76b223bf130..9b111cb5edf 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard.properties @@ -599,7 +599,7 @@ doclet.usage.excludedocfilessubdir.description=\ doclet.usage.group.parameters=\ ,... doclet.usage.group.description=\ - Group specified elements together in overview page.\n\ + Group specified packages or modules together in overview page.\n\ ':' can also be used anywhere in the argument as a separator. doclet.usage.legal-notices.parameters=\ diff --git a/src/jdk.javadoc/share/man/javadoc.md b/src/jdk.javadoc/share/man/javadoc.md index 2ba64dfb2e5..920b16f55b4 100644 --- a/src/jdk.javadoc/share/man/javadoc.md +++ b/src/jdk.javadoc/share/man/javadoc.md @@ -510,8 +510,9 @@ The following options are provided by the standard doclet. `-footer` *html-code* : This option is no longer supported and reports a warning. -`-group` *name* *p1*`,`*p2...* -: Group the specified packages together in the Overview page. +`-group` *name* *g1*`,`*g2...* +: Group the specified packages, or modules when documenting modular code, + together in the Overview page. For historical reasons, `:` can be used as a separator anywhere in the argument instead of `,`. From cbcf401170e0600e48ef74770eaa47c84c7e50b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 24 Jun 2025 16:11:40 +0000 Subject: [PATCH 165/213] 8360403: Disable constant pool ID assert during troubleshooting Reviewed-by: egahlin --- .../share/classes/jdk/jfr/internal/consumer/ConstantMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java index 3b6859304b8..daf6ad7278c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ConstantMap.java @@ -77,7 +77,7 @@ Object get(long id) { if (id != 0) { String msg = "Missing object ID " + id + " in pool " + getName() + ". All IDs should reference an object"; Logger.log(LogTag.JFR_SYSTEM_PARSER, LogLevel.INFO, msg); - assert false : msg; + // assert false : msg; } return null; } From ba0c12231b0f5b680951e75765b5d292f31a2cbc Mon Sep 17 00:00:00 2001 From: David Beaumont Date: Tue, 24 Jun 2025 18:40:24 +0000 Subject: [PATCH 166/213] 8359808: JavaRuntimeURLConnection should only connect to non-directory resources Reviewed-by: alanb, rriggs --- .../jrt/JavaRuntimeURLConnection.java | 139 ++++++------------ test/jdk/sun/net/www/protocol/jrt/Basic.java | 28 +++- 2 files changed, 73 insertions(+), 94 deletions(-) diff --git a/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java index 4e67c962a46..20b735fbdf3 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/jrt/JavaRuntimeURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,116 +28,89 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.UncheckedIOException; import java.net.MalformedURLException; import java.net.URL; -import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; +import jdk.internal.jimage.ImageReader.Node; import jdk.internal.jimage.ImageReaderFactory; -import jdk.internal.loader.Resource; import sun.net.www.ParseUtil; import sun.net.www.URLConnection; /** * URLConnection implementation that can be used to connect to resources - * contained in the runtime image. + * contained in the runtime image. See section "New URI scheme for naming stored + * modules, classes, and resources" in + * JEP 220. */ public class JavaRuntimeURLConnection extends URLConnection { - // ImageReader to access resources in jimage - private static final ImageReader reader = ImageReaderFactory.getImageReader(); + // ImageReader to access resources in jimage. + private static final ImageReader READER = ImageReaderFactory.getImageReader(); - // the module and resource name in the URL + // The module and resource name in the URL (i.e. "jrt:/[$MODULE[/$PATH]]"). + // + // The module name is not percent-decoded, and can be empty. private final String module; - private final String name; + // The resource name permits UTF-8 percent encoding of non-ASCII characters. + private final String path; - // the Resource when connected - private volatile Resource resource; + // The resource node (non-null when connected). + private Node resourceNode; JavaRuntimeURLConnection(URL url) throws IOException { super(url); - String path = url.getPath(); - if (path.isEmpty() || path.charAt(0) != '/') + String urlPath = url.getPath(); + if (urlPath.isEmpty() || urlPath.charAt(0) != '/') { throw new MalformedURLException(url + " missing path or /"); - if (path.length() == 1) { - this.module = null; - this.name = null; + } + int pathSep = urlPath.indexOf('/', 1); + if (pathSep == -1) { + // No trailing resource path. This can never "connect" or return a + // resource (see JEP 220 for details). + this.module = urlPath.substring(1); + this.path = null; } else { - int pos = path.indexOf('/', 1); - if (pos == -1) { - this.module = path.substring(1); - this.name = null; - } else { - this.module = path.substring(1, pos); - this.name = ParseUtil.decode(path.substring(pos+1)); - } + this.module = urlPath.substring(1, pathSep); + this.path = percentDecode(urlPath.substring(pathSep + 1)); } } /** - * Finds a resource in a module, returning {@code null} if the resource - * is not found. + * Finds and caches the resource node associated with this URL and marks the + * connection as "connected". */ - private static Resource findResource(String module, String name) { - if (reader != null) { - URL url = toJrtURL(module, name); - ImageLocation location = reader.findLocation(module, name); - if (location != null) { - return new Resource() { - @Override - public String getName() { - return name; - } - @Override - public URL getURL() { - return url; - } - @Override - public URL getCodeSourceURL() { - return toJrtURL(module); - } - @Override - public InputStream getInputStream() throws IOException { - byte[] resource = reader.getResource(location); - return new ByteArrayInputStream(resource); - } - @Override - public int getContentLength() { - long size = location.getUncompressedSize(); - return (size > Integer.MAX_VALUE) ? -1 : (int) size; - } - }; + private synchronized Node connectResourceNode() throws IOException { + if (resourceNode == null) { + if (module.isEmpty() || path == null) { + throw new IOException("cannot connect to jrt:/" + module); } + Node node = READER.findNode("/modules/" + module + "/" + path); + if (node == null || !node.isResource()) { + throw new IOException(module + "/" + path + " not found"); + } + this.resourceNode = node; + super.connected = true; } - return null; + return resourceNode; } @Override - public synchronized void connect() throws IOException { - if (!connected) { - if (name == null) { - String s = (module == null) ? "" : module; - throw new IOException("cannot connect to jrt:/" + s); - } - resource = findResource(module, name); - if (resource == null) - throw new IOException(module + "/" + name + " not found"); - connected = true; - } + public void connect() throws IOException { + connectResourceNode(); } @Override public InputStream getInputStream() throws IOException { - connect(); - return resource.getInputStream(); + return new ByteArrayInputStream(READER.getResource(connectResourceNode())); } @Override public long getContentLengthLong() { try { - connect(); - return resource.getContentLength(); + return connectResourceNode().size(); } catch (IOException ioe) { return -1L; } @@ -149,27 +122,13 @@ public int getContentLength() { return len > Integer.MAX_VALUE ? -1 : (int)len; } - /** - * Returns a jrt URL for the given module and resource name. - */ - @SuppressWarnings("deprecation") - private static URL toJrtURL(String module, String name) { - try { - return new URL("jrt:/" + module + "/" + name); - } catch (MalformedURLException e) { - throw new InternalError(e); - } - } - - /** - * Returns a jrt URL for the given module. - */ - @SuppressWarnings("deprecation") - private static URL toJrtURL(String module) { + // Perform percent decoding of the resource name/path from the URL. + private static String percentDecode(String path) throws MalformedURLException { + // Any additional special case decoding logic should go here. try { - return new URL("jrt:/" + module); - } catch (MalformedURLException e) { - throw new InternalError(e); + return ParseUtil.decode(path); + } catch (IllegalArgumentException e) { + throw new MalformedURLException(e.getMessage()); } } } diff --git a/test/jdk/sun/net/www/protocol/jrt/Basic.java b/test/jdk/sun/net/www/protocol/jrt/Basic.java index 0f0492c9b39..785920b4a4d 100644 --- a/test/jdk/sun/net/www/protocol/jrt/Basic.java +++ b/test/jdk/sun/net/www/protocol/jrt/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ */ import java.io.IOException; -import java.io.InputStream; import java.net.URL; import java.net.URLConnection; @@ -41,8 +40,29 @@ public class Basic { @DataProvider(name = "urls") public Object[][] urls() { Object[][] data = { - { "jrt:/java.base/java/lang/Object.class", true }, - { "jrt:/java.desktop/java/lang/Object.class", false }, + {"jrt:/java.base/java/lang/Object.class", true}, + // Valid resource with and without percent-encoding. + {"jrt:/java.base/java/lang/Runtime$Version.class", true}, + {"jrt:/java.base/java%2Flang%2FRuntime%24Version.class", true}, + // Unnecessary percent encoding (just Object again). + {"jrt:/java.base/%6a%61%76%61%2f%6c%61%6e%67%2f%4f%62%6a%65%63%74%2e%63%6c%61%73%73", true}, + // Query parameters and fragments are silently ignored. + {"jrt:/java.base/java/lang/Object.class?yes=no", true}, + {"jrt:/java.base/java/lang/Object.class#anchor", true}, + + // Missing resource (no such class). + {"jrt:/java.base/java/lang/NoSuchClass.class", false}, + // Missing resource (wrong module). + {"jrt:/java.desktop/java/lang/Object.class", false}, + // Entries in jimage which don't reference resources. + {"jrt:/modules/java.base/java/lang", false}, + {"jrt:/packages/java.lang", false}, + // Invalid (incomplete/corrupt) URIs. + {"jrt:/", false}, + {"jrt:/java.base", false}, + {"jrt:/java.base/", false}, + // Cannot escape anything in the module name. + {"jrt:/java%2Ebase/java/lang/Object.class", false}, }; return data; } From 509105761492ced0ecdc91aae464dcd016e2a4d7 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Tue, 24 Jun 2025 23:50:35 +0000 Subject: [PATCH 167/213] 8351010: Test java/io/File/GetXSpace.java failed: / usable space 56380809216 > free space 14912244940 Reviewed-by: lancea, rriggs --- test/jdk/java/io/File/GetXSpace.java | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/test/jdk/java/io/File/GetXSpace.java b/test/jdk/java/io/File/GetXSpace.java index 246835d03db..e61880edb2c 100644 --- a/test/jdk/java/io/File/GetXSpace.java +++ b/test/jdk/java/io/File/GetXSpace.java @@ -176,11 +176,11 @@ private static void compare(Space s) { long fs = f.getFreeSpace(); long us = f.getUsableSpace(); - // Verify inequalities us <= fs <= ts (JDK-8349092) + // Verify inequalities us <= ts and fs <= ts (JDK-8349092) if (fs > ts) throw new RuntimeException(f + " free space " + fs + " > total space " + ts); - if (us > fs) - throw new RuntimeException(f + " usable space " + us + " > free space " + fs); + if (us > ts) + throw new RuntimeException(f + " usable space " + us + " > total space " + ts); out.format("%s (%d):%n", s.name(), s.size()); String fmt = " %-4s total = %12d free = %12d usable = %12d%n"; @@ -269,15 +269,9 @@ private static void compare(Space s) { pass(); } - // usable space <= free space - if (us > s.free()) { - // free and usable change dynamically - System.err.println("Warning: us > s.free()"); - if (1.0 - Math.abs((double)s.free()/(double)us) > 0.01) { - fail(s.name() + " usable vs. free space", us, ">", s.free()); - } else { - pass(); - } + // usable space <= total space + if (us > s.total()) { + fail(s.name() + " usable vs. total space", us, ">", s.total()); } else { pass(); } From 7d6c902ce8ffb9b42c264ecff56d4b54206e101b Mon Sep 17 00:00:00 2001 From: Xiaohong Gong Date: Wed, 25 Jun 2025 01:16:08 +0000 Subject: [PATCH 168/213] 8357726: Improve C2 to recognize counted loops with multiple casts in trip counter Reviewed-by: chagedorn, epeter, galder --- src/hotspot/share/opto/loopnode.cpp | 4 +- .../loopopts/TestCountedLoopCastIV.java | 195 ++++++++++++++++++ .../bench/vm/compiler/CountedLoopCastIV.java | 77 +++++++ 3 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestCountedLoopCastIV.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/CountedLoopCastIV.java diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 82446ec3110..e5efdb2a202 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -1689,7 +1689,9 @@ bool PhaseIdealLoop::is_counted_loop(Node* x, IdealLoopTree*&loop, BasicType iv_ return false; } - if (xphi->Opcode() == Op_Cast(iv_bt)) { + // Iteratively uncast the loop induction variable + // until no more CastII/CastLL nodes are found. + while (xphi->Opcode() == Op_Cast(iv_bt)) { xphi = xphi->in(1); } diff --git a/test/hotspot/jtreg/compiler/loopopts/TestCountedLoopCastIV.java b/test/hotspot/jtreg/compiler/loopopts/TestCountedLoopCastIV.java new file mode 100644 index 00000000000..6f31084ac7b --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestCountedLoopCastIV.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package compiler.loopopts; + +import java.util.Arrays; +import java.util.Objects; + +import compiler.lib.generators.*; +import compiler.lib.ir_framework.*; +import jdk.test.lib.Asserts; + + /* + * @test + * @bug 8357726 + * @summary Improve C2 to recognize counted loops with multiple casts in trip counter + * @library /test/lib / + * @run driver compiler.loopopts.TestCountedLoopCastIV DisableUnroll + * @run driver compiler.loopopts.TestCountedLoopCastIV + */ + +public class TestCountedLoopCastIV { + private static final int LEN = 1024; + private static final Generators random = Generators.G; + + private static int[] in; + private static int[] out; + + static { + in = new int[LEN]; + out = new int[LEN]; + random.fill(random.ints(), in); + } + + private static void cleanUp() { + Arrays.fill(out, 0); + } + + private static void verify(int[] ref, int[] res, int start, + int limit, int stride, + int in_offset, int out_offset) { + for (int i = start; i < limit; i += stride) { + Asserts.assertEquals(ref[i + in_offset], res[i + out_offset]); + } + } + + // Test a counted loop with two explicit range checkes + // which will create CastIINodes for loop induction variable. + // In this case, the loop start, limit and stride are + // all constants. + // + // The first IR check with "-XX:LoopUnrollLimit=0" makes sure + // the loop is transformed into exactly one CountedLoopNode, + // verifying the CastII recognition works correctly. + // + // The second IR check ensures the optimization works properly + // with default vm settings. + // + @Test + @IR(counts = {IRNode.COUNTED_LOOP, "1" }, applyIf = {"LoopUnrollLimit", "0"}) + @IR(counts = {IRNode.COUNTED_LOOP, ">0" }) + static void test1() { + for (int i = 0; i < LEN; i += 16) { + Objects.checkIndex(i, LEN - 3); + int a = in[i + 3]; + Objects.checkIndex(i, LEN - 15); + out[i + 15] = a; + } + } + + @Run(test = "test1") + public static void runTest1() { + test1(); + verify(in, out, 0, LEN, 16, 3, 15); + } + + // Similar to test1, but the loop limit is a variable. + @Test + @IR(counts = {IRNode.COUNTED_LOOP, "1" }, applyIf = {"LoopUnrollLimit", "0"}) + @IR(counts = {IRNode.COUNTED_LOOP, ">0" }) + static void test2(int limit) { + for (int i = 0; i < limit; i += 16) { + Objects.checkIndex(i, LEN - 3); + int a = in[i + 3]; + Objects.checkIndex(i, LEN - 15); + out[i + 15] = a; + } + } + + @Run(test = "test2") + private void runTest2() { + cleanUp(); + test2(100); + verify(in, out, 0, 100, 16, 3, 15); + + cleanUp(); + test2(500); + verify(in, out, 0, 500, 16, 3, 15); + + cleanUp(); + test2(LEN); + verify(in, out, 0, LEN, 16, 3, 15); + } + + // Similar to test1 and test2, but the loop is a + // while loop with a variable start and limit. + @Test + @IR(counts = {IRNode.COUNTED_LOOP, "1" }, applyIf = {"LoopUnrollLimit", "0"}) + @IR(counts = {IRNode.COUNTED_LOOP, ">0" }) + static void test3(int start, int limit) { + int i = start; + while (i < limit) { + Objects.checkIndex(i, LEN); + int a = in[i]; + Objects.checkIndex(i, LEN - 3); + out[i + 3] = a; + i++; + } + } + + @Run(test = "test3") + private void runTest3() { + cleanUp(); + test3(0, 100); + verify(in, out, 0, 100, 1, 0, 3); + + cleanUp(); + test3(128, 500); + verify(in, out, 128, 500, 1, 0, 3); + + cleanUp(); + test3(LEN - 128, LEN - 3); + verify(in, out, LEN - 128, LEN - 3, 1, 0, 3); + } + + // Similar to test3, but the type of induction variable + // is long. + @Test + @IR(counts = {IRNode.COUNTED_LOOP, "1" }, applyIf = {"LoopUnrollLimit", "0"}) + @IR(counts = {IRNode.COUNTED_LOOP, ">0" }) + static void test4(long start, long limit) { + for (long i = start; i < limit; i++) { + Objects.checkIndex(i, LEN); + int a = in[(int) i]; + Objects.checkIndex(i, LEN - 3); + out[(int) i + 3] = a; + } + } + + @Run(test = "test4") + private void runTest4() { + cleanUp(); + test3(0, 100); + verify(in, out, 0, 100, 1, 0, 3); + + cleanUp(); + test3(128, 500); + verify(in, out, 128, 500, 1, 0, 3); + + cleanUp(); + test3(LEN - 128, LEN - 3); + verify(in, out, LEN - 128, LEN - 3, 1, 0, 3); + } + + public static void main(String[] args) { + if (args != null && args.length > 0 && args[0].equals("DisableUnroll")) { + TestFramework.runWithFlags("-XX:LoopUnrollLimit=0"); + } else { + if (args != null && args.length != 0) { + throw new RuntimeException("Unexpected args"); + } + TestFramework.run(); + } + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/CountedLoopCastIV.java b/test/micro/org/openjdk/bench/vm/compiler/CountedLoopCastIV.java new file mode 100644 index 00000000000..75e33161dcb --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/CountedLoopCastIV.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * 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.vm.compiler; + +import org.openjdk.jmh.annotations.*; + +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 3, time = 1) +@Measurement(iterations = 5, time = 1) +@BenchmarkMode(Mode.Throughput) +@OutputTimeUnit(TimeUnit.SECONDS) +@State(Scope.Thread) +@Fork(value=3) +public class CountedLoopCastIV { + @Param({"1024", "1536", "2048"}) + private int limit; + + private static final int LEN = 2048; + private int start; + private int[] arr; + + @Setup + public void init() { + arr = new int[LEN]; + for (int i = 0; i < LEN; i++) { + arr[i] = i; + } + + start = 0; + limit = Math.min(limit, LEN - 4); + } + + @Benchmark + public void loop_iv_int() { + int i = start; + while (i < limit) { + Objects.checkIndex(i, LEN - 1); + int a = arr[i + 1]; + Objects.checkIndex(i, LEN - 3); + arr[i + 3] = a; + i++; + } + } + + @Benchmark + public void loop_iv_long() { + for (long i = start; i < limit; i++) { + Objects.checkIndex(i, LEN - 1); + int a = arr[(int)i + 1]; + Objects.checkIndex(i, LEN - 3); + arr[(int)i + 3] = a; + } + } +} From 263e32bb8507310dd4c9a4eca7f6e428303d3a53 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Wed, 25 Jun 2025 04:39:07 +0000 Subject: [PATCH 169/213] 8358694: VM asserts if CodeCacheSegmentSize is not a power of 2 Reviewed-by: shade, dfenacci --- .../flags/jvmFlagConstraintsCompiler.cpp | 7 ++ .../codecache/CodeCacheSegmentSizeTest.java | 77 +++++++++++++++++++ 2 files changed, 84 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/codecache/CodeCacheSegmentSizeTest.java diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp index 0d93b380384..17dc71bc59d 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp @@ -156,6 +156,13 @@ JVMFlag::Error OnStackReplacePercentageConstraintFunc(intx value, bool verbose) } JVMFlag::Error CodeCacheSegmentSizeConstraintFunc(size_t value, bool verbose) { + if (!is_power_of_2(value)) { + JVMFlag::printError(verbose, + "CodeCacheSegmentSize (%zu) must be " + "a power of two\n", CodeCacheSegmentSize); + return JVMFlag::VIOLATES_CONSTRAINT; + } + if (CodeCacheSegmentSize < (size_t)CodeEntryAlignment) { JVMFlag::printError(verbose, "CodeCacheSegmentSize (%zu) must be " diff --git a/test/hotspot/jtreg/compiler/codecache/CodeCacheSegmentSizeTest.java b/test/hotspot/jtreg/compiler/codecache/CodeCacheSegmentSizeTest.java new file mode 100644 index 00000000000..5531bdd1517 --- /dev/null +++ b/test/hotspot/jtreg/compiler/codecache/CodeCacheSegmentSizeTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2025 IBM Corporation. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8358694 + * @summary Verifies that CodeCacheSegmentSize enforces power-of-two constraint: + * - fails gracefully for invalid value + * - succeeds for valid value + * @library /test/lib + * @run driver CodeCacheSegmentSizeTest + */ + +import jdk.test.lib.Platform; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +public class CodeCacheSegmentSizeTest { + public static void main(String[] args) throws Exception { + testInvalidValue(); + testValidValue(); + } + + private static void testInvalidValue() throws Exception { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:+UnlockExperimentalVMOptions", + "-XX:CodeCacheSegmentSize=65", // invalid value (not power of two) + "-version" + ); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + // Ensure no crash (no assert failure) + output.shouldNotContain("assert"); + + // Expected graceful error output + output.shouldContain("CodeCacheSegmentSize (65) must be a power of two"); + output.shouldContain("Error: Could not create the Java Virtual Machine."); + output.shouldContain("Error: A fatal exception has occurred. Program will exit."); + + // Graceful exit with error code 1 + output.shouldHaveExitValue(1); + } + + private static void testValidValue() throws Exception { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:+UnlockExperimentalVMOptions", + "-XX:CodeCacheSegmentSize=64", // a valid power of 2 + "-version" + ); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + + output.shouldHaveExitValue(0); + } +} + From 5c4f92ba9a2b820fa12920400c9037b5d3c37aa4 Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Wed, 25 Jun 2025 06:45:32 +0000 Subject: [PATCH 170/213] 8359788: Internal Error: assert(get_instanceKlass()->is_loaded()) failed: must be at least loaded Reviewed-by: kvn, thartmann --- src/hotspot/share/oops/trainingData.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/oops/trainingData.hpp b/src/hotspot/share/oops/trainingData.hpp index 2be3026881a..6acf19b4d5e 100644 --- a/src/hotspot/share/oops/trainingData.hpp +++ b/src/hotspot/share/oops/trainingData.hpp @@ -34,6 +34,7 @@ #include "memory/metaspaceClosure.hpp" #include "oops/instanceKlass.hpp" #include "oops/method.hpp" +#include "oops/objArrayKlass.hpp" #include "runtime/handles.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/resizeableResourceHash.hpp" @@ -286,7 +287,12 @@ class TrainingData : public Metadata { static bool is_klass_loaded(Klass* k) { if (have_data()) { // If we're running in AOT mode some classes may not be loaded yet - return !k->is_instance_klass() || InstanceKlass::cast(k)->is_loaded(); + if (k->is_objArray_klass()) { + k = ObjArrayKlass::cast(k)->bottom_klass(); + } + if (k->is_instance_klass()) { + return InstanceKlass::cast(k)->is_loaded(); + } } return true; } From 75ce44aa84ebf0f48dd73b98f2bf2d6077473ed1 Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Wed, 25 Jun 2025 08:09:03 +0000 Subject: [PATCH 171/213] 8355319: Update Manpage for Compact Object Headers (Production) Reviewed-by: coleenp, dholmes, phh --- src/java.base/share/man/java.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index a25ef4100e1..3831fc64f88 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -1515,6 +1515,15 @@ These `java` options control the runtime behavior of the Java HotSpot VM. This option is similar to `-Xss`. +`-XX:+UseCompactObjectHeaders` +: Enables compact object headers. By default, this option is disabled. + Enabling this option reduces memory footprint in the Java heap by + 4 bytes per object (on average) and often improves performance. + + The feature remains disabled by default while it continues to be evaluated. + In a future release it is expected to be enabled by default, and + eventually will be the only mode of operation. + `-XX:-UseCompressedOops` : Disables the use of compressed pointers. By default, this option is enabled, and compressed pointers are used. This will automatically limit From 850bc20306e5101d164566f9a8687707492b296b Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Wed, 25 Jun 2025 08:32:51 +0000 Subject: [PATCH 172/213] 8356868: Not all cgroup parameters are made available Reviewed-by: sgehwolf, gziemski --- .../os/linux/cgroupSubsystem_linux.cpp | 15 ++++++-- .../os/linux/cgroupSubsystem_linux.hpp | 19 +++++++++- .../os/linux/cgroupV1Subsystem_linux.cpp | 15 +++++++- .../os/linux/cgroupV1Subsystem_linux.hpp | 37 +++++++++++++++++-- .../os/linux/cgroupV2Subsystem_linux.cpp | 26 +++++++++++-- .../os/linux/cgroupV2Subsystem_linux.hpp | 34 +++++++++++++++++ src/hotspot/os/linux/osContainer_linux.cpp | 12 +++++- src/hotspot/os/linux/osContainer_linux.hpp | 5 ++- src/hotspot/os/linux/os_linux.cpp | 11 +++++- .../jtreg/containers/docker/TestMisc.java | 4 +- 10 files changed, 163 insertions(+), 15 deletions(-) diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index 068914d7049..a9cabc87335 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -62,7 +62,7 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { CgroupV1MemoryController* memory = nullptr; CgroupV1Controller* cpuset = nullptr; CgroupV1CpuController* cpu = nullptr; - CgroupV1Controller* cpuacct = nullptr; + CgroupV1CpuacctController* cpuacct = nullptr; CgroupV1Controller* pids = nullptr; CgroupInfo cg_infos[CG_INFO_LENGTH]; u1 cg_type_flags = INVALID_CGROUPS_GENERIC; @@ -105,9 +105,10 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { CgroupV2CpuController* cpu = new CgroupV2CpuController(CgroupV2Controller(cg_infos[CPU_IDX]._mount_path, cg_infos[CPU_IDX]._cgroup_path, cg_infos[CPU_IDX]._read_only)); + CgroupV2CpuacctController* cpuacct = new CgroupV2CpuacctController(cpu); log_debug(os, container)("Detected cgroups v2 unified hierarchy"); cleanup(cg_infos); - return new CgroupV2Subsystem(memory, cpu, mem_other); + return new CgroupV2Subsystem(memory, cpu, cpuacct, mem_other); } /* @@ -150,7 +151,7 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { cpu = new CgroupV1CpuController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only)); cpu->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "cpuacct") == 0) { - cpuacct = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only); + cpuacct = new CgroupV1CpuacctController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only)); cpuacct->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "pids") == 0) { pids = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only); @@ -856,6 +857,10 @@ jlong CgroupSubsystem::memory_soft_limit_in_bytes() { return memory_controller()->controller()->memory_soft_limit_in_bytes(phys_mem); } +jlong CgroupSubsystem::memory_throttle_limit_in_bytes() { + return memory_controller()->controller()->memory_throttle_limit_in_bytes(); +} + jlong CgroupSubsystem::memory_usage_in_bytes() { return memory_controller()->controller()->memory_usage_in_bytes(); } @@ -884,6 +889,10 @@ int CgroupSubsystem::cpu_shares() { return cpu_controller()->controller()->cpu_shares(); } +jlong CgroupSubsystem::cpu_usage_in_micros() { + return cpuacct_controller()->cpu_usage_in_micros(); +} + void CgroupSubsystem::print_version_specific_info(outputStream* st) { julong phys_mem = os::Linux::physical_memory(); memory_controller()->controller()->print_version_specific_info(st, phys_mem); diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 53b178397f8..f72d1a7fb1e 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -216,6 +216,18 @@ class CgroupCpuController: public CHeapObj { virtual const char* cgroup_path() = 0; }; +// Pure virtual class representing version agnostic CPU accounting controllers +class CgroupCpuacctController: public CHeapObj { + public: + virtual jlong cpu_usage_in_micros() = 0; + virtual bool needs_hierarchy_adjustment() = 0; + virtual bool is_read_only() = 0; + virtual const char* subsystem_path() = 0; + virtual void set_subsystem_path(const char* cgroup_path) = 0; + virtual const char* mount_point() = 0; + virtual const char* cgroup_path() = 0; +}; + // Pure virtual class representing version agnostic memory controllers class CgroupMemoryController: public CHeapObj { public: @@ -224,6 +236,7 @@ class CgroupMemoryController: public CHeapObj { virtual jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) = 0; virtual jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) = 0; virtual jlong memory_soft_limit_in_bytes(julong upper_bound) = 0; + virtual jlong memory_throttle_limit_in_bytes() = 0; virtual jlong memory_max_usage_in_bytes() = 0; virtual jlong rss_usage_in_bytes() = 0; virtual jlong cache_usage_in_bytes() = 0; @@ -250,15 +263,19 @@ class CgroupSubsystem: public CHeapObj { virtual const char * container_type() = 0; virtual CachingCgroupController* memory_controller() = 0; virtual CachingCgroupController* cpu_controller() = 0; + virtual CgroupCpuacctController* cpuacct_controller() = 0; int cpu_quota(); int cpu_period(); int cpu_shares(); + jlong cpu_usage_in_micros(); + jlong memory_usage_in_bytes(); jlong memory_and_swap_limit_in_bytes(); jlong memory_and_swap_usage_in_bytes(); jlong memory_soft_limit_in_bytes(); + jlong memory_throttle_limit_in_bytes(); jlong memory_max_usage_in_bytes(); jlong rss_usage_in_bytes(); jlong cache_usage_in_bytes(); diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index 8d9c3edb72a..f65da207062 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -248,10 +248,16 @@ jlong CgroupV1MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { } } +jlong CgroupV1MemoryController::memory_throttle_limit_in_bytes() { + // Log this string at trace level so as to make tests happy. + log_trace(os, container)("Memory Throttle Limit is not supported."); + return OSCONTAINER_ERROR; // not supported +} + // Constructor CgroupV1Subsystem::CgroupV1Subsystem(CgroupV1Controller* cpuset, CgroupV1CpuController* cpu, - CgroupV1Controller* cpuacct, + CgroupV1CpuacctController* cpuacct, CgroupV1Controller* pids, CgroupV1MemoryController* memory) : _cpuset(cpuset), @@ -416,6 +422,13 @@ int CgroupV1CpuController::cpu_shares() { return shares_int; } +jlong CgroupV1CpuacctController::cpu_usage_in_micros() { + julong cpu_usage; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/cpuacct.usage", "CPU Usage", cpu_usage); + // Output is in nanoseconds, convert to microseconds. + return (jlong)cpu_usage / 1000; +} + /* pids_max * * Return the maximum number of tasks available to the process diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index 0c191ab91c7..a56ad455165 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,6 +82,7 @@ class CgroupV1MemoryController final : public CgroupMemoryController { jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) override; jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; + jlong memory_throttle_limit_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; jlong cache_usage_in_bytes() override; @@ -140,12 +141,41 @@ class CgroupV1CpuController final : public CgroupCpuController { } }; +class CgroupV1CpuacctController final : public CgroupCpuacctController { + + private: + CgroupV1Controller _reader; + CgroupV1Controller* reader() { return &_reader; } + public: + jlong cpu_usage_in_micros() override; + void set_subsystem_path(const char *cgroup_path) override { + reader()->set_subsystem_path(cgroup_path); + } + bool is_read_only() override { + return reader()->is_read_only(); + } + const char* subsystem_path() override { + return reader()->subsystem_path(); + } + const char* mount_point() override { + return reader()->mount_point(); + } + bool needs_hierarchy_adjustment() override { + return reader()->needs_hierarchy_adjustment(); + } + const char* cgroup_path() override { return reader()->cgroup_path(); } + + public: + CgroupV1CpuacctController(const CgroupV1Controller& reader) : _reader(reader) { + } +}; + class CgroupV1Subsystem: public CgroupSubsystem { public: CgroupV1Subsystem(CgroupV1Controller* cpuset, CgroupV1CpuController* cpu, - CgroupV1Controller* cpuacct, + CgroupV1CpuacctController* cpuacct, CgroupV1Controller* pids, CgroupV1MemoryController* memory); @@ -165,13 +195,14 @@ class CgroupV1Subsystem: public CgroupSubsystem { } CachingCgroupController* memory_controller() { return _memory; } CachingCgroupController* cpu_controller() { return _cpu; } + CgroupCpuacctController* cpuacct_controller() { return _cpuacct; } private: /* controllers */ CachingCgroupController* _memory = nullptr; CgroupV1Controller* _cpuset = nullptr; CachingCgroupController* _cpu = nullptr; - CgroupV1Controller* _cpuacct = nullptr; + CgroupV1CpuacctController* _cpuacct = nullptr; CgroupV1Controller* _pids = nullptr; }; diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index cbadbb9db02..6472fdfccc5 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, 2025, Red Hat Inc. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -114,12 +115,14 @@ int CgroupV2CpuController::cpu_quota() { // Constructor CgroupV2Subsystem::CgroupV2Subsystem(CgroupV2MemoryController * memory, CgroupV2CpuController* cpu, + CgroupV2CpuacctController* cpuacct, CgroupV2Controller unified) : _unified(unified) { CgroupUtil::adjust_controller(memory); CgroupUtil::adjust_controller(cpu); _memory = new CachingCgroupController(memory); _cpu = new CachingCgroupController(cpu); + _cpuacct = cpuacct; } bool CgroupV2Subsystem::is_containerized() { @@ -152,6 +155,17 @@ int CgroupV2CpuController::cpu_period() { return period; } +jlong CgroupV2CpuController::cpu_usage_in_micros() { + julong cpu_usage; + bool is_ok = reader()->read_numerical_key_value("/cpu.stat", "usage_usec", &cpu_usage); + if (!is_ok) { + log_trace(os, container)("CPU Usage failed: %d", OSCONTAINER_ERROR); + return OSCONTAINER_ERROR; + } + log_trace(os, container)("CPU Usage is: " JULONG_FORMAT, cpu_usage); + return (jlong)cpu_usage; +} + /* memory_usage_in_bytes * * Return the amount of used memory used by this cgroup and descendents @@ -173,10 +187,16 @@ jlong CgroupV2MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { return mem_soft_limit; } +jlong CgroupV2MemoryController::memory_throttle_limit_in_bytes() { + jlong mem_throttle_limit; + CONTAINER_READ_NUMBER_CHECKED_MAX(reader(), "/memory.high", "Memory Throttle Limit", mem_throttle_limit); + return mem_throttle_limit; +} + jlong CgroupV2MemoryController::memory_max_usage_in_bytes() { - // Log this string at trace level so as to make tests happy. - log_trace(os, container)("Maximum Memory Usage is not supported."); - return OSCONTAINER_ERROR; // not supported + julong mem_max_usage; + CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.peak", "Maximum Memory Usage", mem_max_usage); + return mem_max_usage; } jlong CgroupV2MemoryController::rss_usage_in_bytes() { diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp index 56dcadd670f..e26f37925ca 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2020, 2024, Red Hat Inc. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,6 +62,34 @@ class CgroupV2CpuController: public CgroupCpuController { int cpu_quota() override; int cpu_period() override; int cpu_shares() override; + jlong cpu_usage_in_micros(); + bool is_read_only() override { + return reader()->is_read_only(); + } + const char* subsystem_path() override { + return reader()->subsystem_path(); + } + bool needs_hierarchy_adjustment() override { + return reader()->needs_hierarchy_adjustment(); + } + void set_subsystem_path(const char* cgroup_path) override { + reader()->set_subsystem_path(cgroup_path); + } + const char* mount_point() override { return reader()->mount_point(); } + const char* cgroup_path() override { return reader()->cgroup_path(); } +}; + +class CgroupV2CpuacctController: public CgroupCpuacctController { + private: + CgroupV2CpuController* _reader; + CgroupV2CpuController* reader() { return _reader; } + public: + CgroupV2CpuacctController(CgroupV2CpuController* reader) : _reader(reader) { + } + // In cgroup v2, cpu usage is a part of the cpu controller. + jlong cpu_usage_in_micros() override { + return reader()->cpu_usage_in_micros(); + } bool is_read_only() override { return reader()->is_read_only(); } @@ -89,6 +118,7 @@ class CgroupV2MemoryController final: public CgroupMemoryController { jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swp) override; jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swp) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; + jlong memory_throttle_limit_in_bytes() override; jlong memory_usage_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; @@ -118,11 +148,14 @@ class CgroupV2Subsystem: public CgroupSubsystem { CachingCgroupController* _memory = nullptr; CachingCgroupController* _cpu = nullptr; + CgroupCpuacctController* _cpuacct = nullptr; + CgroupV2Controller* unified() { return &_unified; } public: CgroupV2Subsystem(CgroupV2MemoryController * memory, CgroupV2CpuController* cpu, + CgroupV2CpuacctController* cpuacct, CgroupV2Controller unified); char * cpu_cpuset_cpus() override; @@ -137,6 +170,7 @@ class CgroupV2Subsystem: public CgroupSubsystem { } CachingCgroupController* memory_controller() override { return _memory; } CachingCgroupController* cpu_controller() override { return _cpu; } + CgroupCpuacctController* cpuacct_controller() override { return _cpuacct; }; }; #endif // CGROUP_V2_SUBSYSTEM_LINUX_HPP diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp index ecac7307c30..2ba4c252659 100644 --- a/src/hotspot/os/linux/osContainer_linux.cpp +++ b/src/hotspot/os/linux/osContainer_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,6 +122,11 @@ jlong OSContainer::memory_soft_limit_in_bytes() { return cgroup_subsystem->memory_soft_limit_in_bytes(); } +jlong OSContainer::memory_throttle_limit_in_bytes() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->memory_throttle_limit_in_bytes(); +} + jlong OSContainer::memory_usage_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); return cgroup_subsystem->memory_usage_in_bytes(); @@ -177,6 +182,11 @@ int OSContainer::cpu_shares() { return cgroup_subsystem->cpu_shares(); } +jlong OSContainer::cpu_usage_in_micros() { + assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); + return cgroup_subsystem->cpu_usage_in_micros(); +} + jlong OSContainer::pids_max() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); return cgroup_subsystem->pids_max(); diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp index dd29c7a4769..3c270e8ea50 100644 --- a/src/hotspot/os/linux/osContainer_linux.hpp +++ b/src/hotspot/os/linux/osContainer_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,6 +54,7 @@ class OSContainer: AllStatic { static jlong memory_and_swap_limit_in_bytes(); static jlong memory_and_swap_usage_in_bytes(); static jlong memory_soft_limit_in_bytes(); + static jlong memory_throttle_limit_in_bytes(); static jlong memory_usage_in_bytes(); static jlong memory_max_usage_in_bytes(); static jlong rss_usage_in_bytes(); @@ -69,6 +70,8 @@ class OSContainer: AllStatic { static int cpu_shares(); + static jlong cpu_usage_in_micros(); + static jlong pids_max(); static jlong pids_current(); }; diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index ff2195d3839..1a23c956f35 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2487,9 +2487,18 @@ bool os::Linux::print_container_info(outputStream* st) { st->print_cr("%s", i == OSCONTAINER_ERROR ? "not supported" : "no shares"); } + jlong j = OSContainer::cpu_usage_in_micros(); + st->print("cpu_usage_in_micros: "); + if (j >= 0) { + st->print_cr(JLONG_FORMAT, j); + } else { + st->print_cr("%s", j == OSCONTAINER_ERROR ? "not supported" : "no usage"); + } + OSContainer::print_container_helper(st, OSContainer::memory_limit_in_bytes(), "memory_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_and_swap_limit_in_bytes(), "memory_and_swap_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_soft_limit_in_bytes(), "memory_soft_limit_in_bytes"); + OSContainer::print_container_helper(st, OSContainer::memory_throttle_limit_in_bytes(), "memory_throttle_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_usage_in_bytes(), "memory_usage_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_max_usage_in_bytes(), "memory_max_usage_in_bytes"); OSContainer::print_container_helper(st, OSContainer::rss_usage_in_bytes(), "rss_usage_in_bytes"); @@ -2497,7 +2506,7 @@ bool os::Linux::print_container_info(outputStream* st) { OSContainer::print_version_specific_info(st); - jlong j = OSContainer::pids_max(); + j = OSContainer::pids_max(); st->print("maximum number of tasks: "); if (j > 0) { st->print_cr(JLONG_FORMAT, j); diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index a811666999b..1ca3540683c 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,9 +110,11 @@ private static void checkContainerInfo(OutputAnalyzer out) throws Exception { "CPU Shares", "CPU Quota", "CPU Period", + "CPU Usage", "OSContainer::active_processor_count", "Memory Limit", "Memory Soft Limit", + "Memory Throttle Limit", "Memory Usage", "Maximum Memory Usage", "memory_max_usage_in_bytes", From f71d64fbeb0c196fd825241ff86d3a103d05a842 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Wed, 25 Jun 2025 08:59:46 +0000 Subject: [PATCH 173/213] 8360405: [PPC64] some environments don't support mfdscr instruction Reviewed-by: haosun, rrich --- src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 12 ++- src/hotspot/cpu/ppc/stubGenerator_ppc.cpp | 85 ++++++++++++++-------- src/hotspot/cpu/ppc/vm_version_ppc.cpp | 9 ++- src/hotspot/cpu/ppc/vm_version_ppc.hpp | 7 +- 4 files changed, 73 insertions(+), 40 deletions(-) diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index 857911214c5..396a50427f8 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -3928,8 +3928,10 @@ void MacroAssembler::kernel_crc32_vpmsum_aligned(Register crc, Register buf, Reg Label L_outer_loop, L_inner_loop, L_last; // Set DSCR pre-fetch to deepest. - load_const_optimized(t0, VM_Version::_dscr_val | 7); - mtdscr(t0); + if (VM_Version::has_mfdscr()) { + load_const_optimized(t0, VM_Version::_dscr_val | 7); + mtdscr(t0); + } mtvrwz(VCRC, crc); // crc lives in VCRC, now @@ -4073,8 +4075,10 @@ void MacroAssembler::kernel_crc32_vpmsum_aligned(Register crc, Register buf, Reg // ********** Main loop end ********** // Restore DSCR pre-fetch value. - load_const_optimized(t0, VM_Version::_dscr_val); - mtdscr(t0); + if (VM_Version::has_mfdscr()) { + load_const_optimized(t0, VM_Version::_dscr_val); + mtdscr(t0); + } // ********** Simple loop for remaining 16 byte blocks ********** { diff --git a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp index ba4b00197fb..a2b25376837 100644 --- a/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp +++ b/src/hotspot/cpu/ppc/stubGenerator_ppc.cpp @@ -952,8 +952,10 @@ class StubGenerator: public StubCodeGenerator { address start_pc = __ pc(); Register tmp1 = R6_ARG4; // probably copy stub would have changed value reset it. - __ load_const_optimized(tmp1, VM_Version::_dscr_val); - __ mtdscr(tmp1); + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp1, VM_Version::_dscr_val); + __ mtdscr(tmp1); + } __ li(R3_RET, 0); // return 0 __ blr(); return start_pc; @@ -1070,9 +1072,10 @@ class StubGenerator: public StubCodeGenerator { __ dcbt(R3_ARG1, 0); // If supported set DSCR pre-fetch to deepest. - __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); - __ mtdscr(tmp2); - + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); + __ mtdscr(tmp2); + } __ li(tmp1, 16); // Backbranch target aligned to 32-byte. Not 16-byte align as @@ -1092,8 +1095,10 @@ class StubGenerator: public StubCodeGenerator { __ bdnz(l_10); // Dec CTR and loop if not zero. // Restore DSCR pre-fetch value. - __ load_const_optimized(tmp2, VM_Version::_dscr_val); - __ mtdscr(tmp2); + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val); + __ mtdscr(tmp2); + } } // FasterArrayCopy @@ -1344,8 +1349,10 @@ class StubGenerator: public StubCodeGenerator { __ dcbt(R3_ARG1, 0); // If supported set DSCR pre-fetch to deepest. - __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); - __ mtdscr(tmp2); + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); + __ mtdscr(tmp2); + } __ li(tmp1, 16); // Backbranch target aligned to 32-byte. It's not aligned 16-byte @@ -1365,8 +1372,11 @@ class StubGenerator: public StubCodeGenerator { __ bdnz(l_9); // Dec CTR and loop if not zero. // Restore DSCR pre-fetch value. - __ load_const_optimized(tmp2, VM_Version::_dscr_val); - __ mtdscr(tmp2); + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val); + __ mtdscr(tmp2); + } + } // FasterArrayCopy __ bind(l_6); @@ -1527,9 +1537,10 @@ class StubGenerator: public StubCodeGenerator { __ dcbt(R3_ARG1, 0); // Set DSCR pre-fetch to deepest. - __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); - __ mtdscr(tmp2); - + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); + __ mtdscr(tmp2); + } __ li(tmp1, 16); // Backbranch target aligned to 32-byte. Not 16-byte align as @@ -1549,9 +1560,10 @@ class StubGenerator: public StubCodeGenerator { __ bdnz(l_7); // Dec CTR and loop if not zero. // Restore DSCR pre-fetch value. - __ load_const_optimized(tmp2, VM_Version::_dscr_val); - __ mtdscr(tmp2); - + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val); + __ mtdscr(tmp2); + } } // FasterArrayCopy @@ -1672,9 +1684,10 @@ class StubGenerator: public StubCodeGenerator { __ dcbt(R3_ARG1, 0); // Set DSCR pre-fetch to deepest. - __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); - __ mtdscr(tmp2); - + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); + __ mtdscr(tmp2); + } __ li(tmp1, 16); // Backbranch target aligned to 32-byte. Not 16-byte align as @@ -1694,8 +1707,10 @@ class StubGenerator: public StubCodeGenerator { __ bdnz(l_4); // Restore DSCR pre-fetch value. - __ load_const_optimized(tmp2, VM_Version::_dscr_val); - __ mtdscr(tmp2); + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val); + __ mtdscr(tmp2); + } __ cmpwi(CR0, R5_ARG3, 0); __ beq(CR0, l_6); @@ -1788,9 +1803,10 @@ class StubGenerator: public StubCodeGenerator { __ dcbt(R3_ARG1, 0); // Set DSCR pre-fetch to deepest. - __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); - __ mtdscr(tmp2); - + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); + __ mtdscr(tmp2); + } __ li(tmp1, 16); // Backbranch target aligned to 32-byte. Not 16-byte align as @@ -1810,8 +1826,10 @@ class StubGenerator: public StubCodeGenerator { __ bdnz(l_5); // Dec CTR and loop if not zero. // Restore DSCR pre-fetch value. - __ load_const_optimized(tmp2, VM_Version::_dscr_val); - __ mtdscr(tmp2); + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val); + __ mtdscr(tmp2); + } } // FasterArrayCopy @@ -1910,9 +1928,10 @@ class StubGenerator: public StubCodeGenerator { __ dcbt(R3_ARG1, 0); // Set DSCR pre-fetch to deepest. - __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); - __ mtdscr(tmp2); - + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val | 7); + __ mtdscr(tmp2); + } __ li(tmp1, 16); // Backbranch target aligned to 32-byte. Not 16-byte align as @@ -1932,8 +1951,10 @@ class StubGenerator: public StubCodeGenerator { __ bdnz(l_4); // Restore DSCR pre-fetch value. - __ load_const_optimized(tmp2, VM_Version::_dscr_val); - __ mtdscr(tmp2); + if (VM_Version::has_mfdscr()) { + __ load_const_optimized(tmp2, VM_Version::_dscr_val); + __ mtdscr(tmp2); + } __ cmpwi(CR0, R5_ARG3, 0); __ beq(CR0, l_1); diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index ad5e915a838..ec2766ac75b 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -80,7 +80,9 @@ void VM_Version::initialize() { "%zu on this machine", PowerArchitecturePPC64); // Power 8: Configure Data Stream Control Register. - config_dscr(); + if (VM_Version::has_mfdscr()) { + config_dscr(); + } if (!UseSIGTRAP) { MSG(TrapBasedICMissChecks); @@ -170,7 +172,8 @@ void VM_Version::initialize() { // Create and print feature-string. char buf[(num_features+1) * 16]; // Max 16 chars per feature. jio_snprintf(buf, sizeof(buf), - "ppc64 sha aes%s%s", + "ppc64 sha aes%s%s%s", + (has_mfdscr() ? " mfdscr" : ""), (has_darn() ? " darn" : ""), (has_brw() ? " brw" : "") // Make sure number of %s matches num_features! @@ -488,6 +491,7 @@ void VM_Version::determine_features() { uint32_t *code = (uint32_t *)a->pc(); // Keep R3_ARG1 unmodified, it contains &field (see below). // Keep R4_ARG2 unmodified, it contains offset = 0 (see below). + a->mfdscr(R0); a->darn(R7); a->brw(R5, R6); a->blr(); @@ -524,6 +528,7 @@ void VM_Version::determine_features() { // determine which instructions are legal. int feature_cntr = 0; + if (code[feature_cntr++]) features |= mfdscr_m; if (code[feature_cntr++]) features |= darn_m; if (code[feature_cntr++]) features |= brw_m; diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index 18dfd843c19..9588edc4bf8 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -32,12 +32,14 @@ class VM_Version: public Abstract_VM_Version { protected: enum Feature_Flag { + mfdscr, darn, brw, num_features // last entry to count features }; enum Feature_Flag_Set { unknown_m = 0, + mfdscr_m = (1 << mfdscr ), darn_m = (1 << darn ), brw_m = (1 << brw ), all_features_m = (unsigned long)-1 @@ -67,8 +69,9 @@ class VM_Version: public Abstract_VM_Version { static bool is_determine_features_test_running() { return _is_determine_features_test_running; } // CPU instruction support - static bool has_darn() { return (_features & darn_m) != 0; } - static bool has_brw() { return (_features & brw_m) != 0; } + static bool has_mfdscr() { return (_features & mfdscr_m) != 0; } // Power8, but may be unavailable (QEMU) + static bool has_darn() { return (_features & darn_m) != 0; } + static bool has_brw() { return (_features & brw_m) != 0; } // Assembler testing static void allow_all(); From 1fa090524a7c3bb5f2c92fb0f7217b9277ade9d9 Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Wed, 25 Jun 2025 09:45:57 +0000 Subject: [PATCH 174/213] 8359268: 3 JNI exception pending defect groups in 2 files Reviewed-by: djelinski --- src/java.base/share/native/libnet/net_util.c | 13 +++---------- src/java.base/share/native/libnet/net_util.h | 5 +++++ src/java.base/unix/native/libnet/net_util_md.c | 7 +++++-- .../windows/native/libnet/Inet4AddressImpl.c | 9 ++++++--- .../windows/native/libnet/Inet6AddressImpl.c | 8 ++++++-- 5 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/java.base/share/native/libnet/net_util.c b/src/java.base/share/native/libnet/net_util.c index b61ead11dd5..5b356d04b3c 100644 --- a/src/java.base/share/native/libnet/net_util.c +++ b/src/java.base/share/native/libnet/net_util.c @@ -91,14 +91,7 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) } static int enhancedExceptionsInitialized = 0; -static int enhancedExceptionsAllowed = -1; - -#define CHECK_NULL_THROW_ERROR(X) \ - if (X == NULL) { \ - JNU_ThrowByName(env, "java/lang/InternalError", \ - "can't initialize enhanced exceptions"); \ - return -1; \ - } +static int enhancedExceptionsAllowed = 0; int getEnhancedExceptionsAllowed(JNIEnv *env) { jclass cls; @@ -108,9 +101,9 @@ int getEnhancedExceptionsAllowed(JNIEnv *env) { return enhancedExceptionsAllowed; } cls = (*env)->FindClass(env, "jdk/internal/util/Exceptions"); - CHECK_NULL_THROW_ERROR(cls); + CHECK_NULL_RETURN(cls, ENH_INIT_ERROR); fid = (*env)->GetStaticFieldID(env, cls, "enhancedNonSocketExceptionText", "Z"); - CHECK_NULL_THROW_ERROR(fid); + CHECK_NULL_RETURN(fid, ENH_INIT_ERROR); enhancedExceptionsAllowed = (*env)->GetStaticBooleanField(env, cls, fid); enhancedExceptionsInitialized = 1; return enhancedExceptionsAllowed; diff --git a/src/java.base/share/native/libnet/net_util.h b/src/java.base/share/native/libnet/net_util.h index 89537a7f47d..92b812b1868 100644 --- a/src/java.base/share/native/libnet/net_util.h +++ b/src/java.base/share/native/libnet/net_util.h @@ -183,6 +183,11 @@ int lookupCharacteristicsToAddressFamily(int characteristics); int addressesInSystemOrder(int characteristics); +/* return codes */ +#define ENH_INIT_ERROR -1 /* initialization error: check exceptions */ +#define ENH_DISABLED 0 /* enhanced exceptions disabled */ +#define ENH_ENABLED 1 /* enhanced exceptions enabled */ + int getEnhancedExceptionsAllowed(JNIEnv *env); #endif /* NET_UTILS_H */ diff --git a/src/java.base/unix/native/libnet/net_util_md.c b/src/java.base/unix/native/libnet/net_util_md.c index d50130d188b..9bb6a026961 100644 --- a/src/java.base/unix/native/libnet/net_util_md.c +++ b/src/java.base/unix/native/libnet/net_util_md.c @@ -188,8 +188,11 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, if (error_string == NULL) error_string = "unknown error"; int enhancedExceptions = getEnhancedExceptionsAllowed(env); + if (enhancedExceptions == ENH_INIT_ERROR && (*env)->ExceptionCheck(env)) { + return; + } - if (enhancedExceptions) { + if (enhancedExceptions == ENH_ENABLED) { size = strlen(hostname); } else { size = 0; @@ -200,7 +203,7 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, if (buf) { jstring s; int n; - if (enhancedExceptions) { + if (enhancedExceptions == ENH_ENABLED) { n = snprintf(buf, size, "%s: %s", hostname, error_string); } else { n = snprintf(buf, size, " %s", error_string); diff --git a/src/java.base/windows/native/libnet/Inet4AddressImpl.c b/src/java.base/windows/native/libnet/Inet4AddressImpl.c index 0ef0cae5be7..93210b0f6a5 100644 --- a/src/java.base/windows/native/libnet/Inet4AddressImpl.c +++ b/src/java.base/windows/native/libnet/Inet4AddressImpl.c @@ -88,9 +88,12 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, if (error) { // report error - NET_ThrowByNameWithLastError( - env, "java/net/UnknownHostException", - getEnhancedExceptionsAllowed(env) ? hostname : ""); + int enh = getEnhancedExceptionsAllowed(env); + if (enh == ENH_INIT_ERROR && (*env)->ExceptionCheck(env)) { + goto cleanupAndReturn; + } + const char *hmsg = (enh == ENH_ENABLED) ? hostname : ""; + NET_ThrowByNameWithLastError( env, "java/net/UnknownHostException", hmsg); goto cleanupAndReturn; } else { int i = 0; diff --git a/src/java.base/windows/native/libnet/Inet6AddressImpl.c b/src/java.base/windows/native/libnet/Inet6AddressImpl.c index 0281e2ddecb..6e5306164e1 100644 --- a/src/java.base/windows/native/libnet/Inet6AddressImpl.c +++ b/src/java.base/windows/native/libnet/Inet6AddressImpl.c @@ -83,8 +83,12 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, if (error) { // report error - NET_ThrowByNameWithLastError(env, "java/net/UnknownHostException", - getEnhancedExceptionsAllowed(env) ? hostname : ""); + int enh = getEnhancedExceptionsAllowed(env); + if (enh == ENH_INIT_ERROR && (*env)->ExceptionCheck(env)) { + goto cleanupAndReturn; + } + const char *hmsg = (enh == ENH_ENABLED) ? hostname : ""; + NET_ThrowByNameWithLastError(env, "java/net/UnknownHostException", hmsg); goto cleanupAndReturn; } else { int i = 0, inetCount = 0, inet6Count = 0, inetIndex = 0, From f2ef809719cbb14f90a0a5f673e10e7c74fa0f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Wed, 25 Jun 2025 13:00:08 +0000 Subject: [PATCH 175/213] 8354727: CompilationPolicy creates too many compiler threads when code cache space is scarce Co-authored-by: Aleksey Shipilev Reviewed-by: kvn, shade --- src/hotspot/share/compiler/compilationPolicy.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/compiler/compilationPolicy.cpp b/src/hotspot/share/compiler/compilationPolicy.cpp index 02dec8d957b..fd1357398f5 100644 --- a/src/hotspot/share/compiler/compilationPolicy.cpp +++ b/src/hotspot/share/compiler/compilationPolicy.cpp @@ -571,8 +571,15 @@ void CompilationPolicy::initialize() { #ifdef COMPILER2 c2_size = C2Compiler::initial_code_buffer_size(); #endif - size_t buffer_size = c1_only ? c1_size : (c1_size/3 + 2*c2_size/3); - size_t max_count = (ReservedCodeCacheSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / buffer_size; + size_t buffer_size = 0; + if (c1_only) { + buffer_size = c1_size; + } else if (c2_only) { + buffer_size = c2_size; + } else { + buffer_size = c1_size / 3 + 2 * c2_size / 3; + } + size_t max_count = (NonNMethodCodeHeapSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / buffer_size; if ((size_t)count > max_count) { // Lower the compiler count such that all buffers fit into the code cache count = MAX2((int)max_count, min_count); @@ -591,7 +598,7 @@ void CompilationPolicy::initialize() { count = 3; FLAG_SET_ERGO(CICompilerCount, count); } -#endif +#endif // _LP64 if (c1_only) { // No C2 compiler threads are needed From 878497fb85b9f7d066829b745324028f9f8cdc60 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 25 Jun 2025 15:16:44 +0000 Subject: [PATCH 176/213] 8360178: TestArguments.atojulong gtest has incorrect format string Reviewed-by: dholmes --- test/hotspot/gtest/runtime/test_arguments.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/hotspot/gtest/runtime/test_arguments.cpp b/test/hotspot/gtest/runtime/test_arguments.cpp index 132157c98b6..074636fea0d 100644 --- a/test/hotspot/gtest/runtime/test_arguments.cpp +++ b/test/hotspot/gtest/runtime/test_arguments.cpp @@ -22,7 +22,6 @@ */ #include "jvm.h" -#include "unittest.hpp" #include "runtime/arguments.hpp" #include "runtime/flags/jvmFlag.hpp" #include "utilities/align.hpp" @@ -30,6 +29,8 @@ #include +#include "unittest.hpp" + class ArgumentsTest : public ::testing::Test { public: static intx parse_xss_inner_annotated(const char* str, jint expected_err, const char* file, int line_number); @@ -57,7 +58,7 @@ class ArgumentsTest : public ::testing::Test { TEST_F(ArgumentsTest, atojulong) { char ullong_max[32]; - int ret = jio_snprintf(ullong_max, sizeof(ullong_max), JULONG_FORMAT, ULLONG_MAX); + int ret = jio_snprintf(ullong_max, sizeof(ullong_max), "%llu", ULLONG_MAX); ASSERT_NE(-1, ret); julong value; From 4e1bf31368df9f6ba110a2b8c678cf1a22607535 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 25 Jun 2025 15:36:02 +0000 Subject: [PATCH 177/213] 8360523: Parallel: Remove unused local variable in MutableNUMASpace::initialize Reviewed-by: stefank, kbarrett --- src/hotspot/share/gc/parallel/mutableNUMASpace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 0375e969586..7ab515fffb4 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -412,7 +412,7 @@ void MutableNUMASpace::initialize(MemRegion mr, MutableSpace *s = ls->space(); old_region = s->region(); - size_t chunk_byte_size = 0, old_chunk_byte_size = 0; + size_t chunk_byte_size = 0; if (i < lgrp_spaces()->length() - 1) { if (!UseAdaptiveNUMAChunkSizing || (UseAdaptiveNUMAChunkSizing && NUMAChunkResizeWeight == 0) || From 52c6044fe48f2e964be4c4603a865143f0d43f90 Mon Sep 17 00:00:00 2001 From: Suchismith Roy Date: Wed, 25 Jun 2025 15:39:57 +0000 Subject: [PATCH 178/213] 8349077: Rename GenerationCounters::update_all Reviewed-by: ayang, stefank --- .../gc/epsilon/epsilonMonitoringSupport.cpp | 2 +- .../share/gc/g1/g1MonitoringSupport.cpp | 4 ++-- src/hotspot/share/gc/parallel/psOldGen.cpp | 4 ++-- src/hotspot/share/gc/parallel/psYoungGen.cpp | 2 +- .../share/gc/serial/defNewGeneration.cpp | 2 +- .../share/gc/serial/tenuredGeneration.cpp | 2 +- .../share/gc/shared/generationCounters.cpp | 2 +- .../share/gc/shared/generationCounters.hpp | 4 ++-- .../shenandoahMonitoringSupport.cpp | 2 +- src/hotspot/share/gc/z/zServiceability.cpp | 24 ++----------------- 10 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp index a2ae6f8a14a..33a2690f777 100644 --- a/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp @@ -91,7 +91,7 @@ class EpsilonGenerationCounters : public GenerationCounters { {}; void update_all() { - GenerationCounters::update_all(_heap->capacity()); + GenerationCounters::update_capacity(_heap->capacity()); } }; diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp index 6d1ffdb7c00..26364705a9d 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp @@ -62,7 +62,7 @@ class G1YoungGenerationCounters : public G1GenerationCounters { void update_all() { size_t committed = _monitoring_support->young_gen_committed(); - GenerationCounters::update_all(committed); + GenerationCounters::update_capacity(committed); } }; @@ -83,7 +83,7 @@ class G1OldGenerationCounters : public G1GenerationCounters { void update_all() { size_t committed = _monitoring_support->old_gen_committed(); - GenerationCounters::update_all(committed); + GenerationCounters::update_capacity(committed); } }; diff --git a/src/hotspot/share/gc/parallel/psOldGen.cpp b/src/hotspot/share/gc/parallel/psOldGen.cpp index bc25683e00f..cedad78be30 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.cpp +++ b/src/hotspot/share/gc/parallel/psOldGen.cpp @@ -234,7 +234,7 @@ bool PSOldGen::expand_by(size_t bytes) { post_resize(); if (UsePerfData) { _space_counters->update_capacity(); - _gen_counters->update_all(_virtual_space->committed_size()); + _gen_counters->update_capacity(_virtual_space->committed_size()); } } @@ -366,7 +366,7 @@ void PSOldGen::print_on(outputStream* st) const { void PSOldGen::update_counters() { if (UsePerfData) { _space_counters->update_all(); - _gen_counters->update_all(_virtual_space->committed_size()); + _gen_counters->update_capacity(_virtual_space->committed_size()); } } diff --git a/src/hotspot/share/gc/parallel/psYoungGen.cpp b/src/hotspot/share/gc/parallel/psYoungGen.cpp index bf77a0dde93..4024109a4a0 100644 --- a/src/hotspot/share/gc/parallel/psYoungGen.cpp +++ b/src/hotspot/share/gc/parallel/psYoungGen.cpp @@ -810,7 +810,7 @@ void PSYoungGen::update_counters() { _eden_counters->update_all(); _from_counters->update_all(); _to_counters->update_all(); - _gen_counters->update_all(_virtual_space->committed_size()); + _gen_counters->update_capacity(_virtual_space->committed_size()); } } diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 61b0ccad191..cb36207ff47 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -814,7 +814,7 @@ void DefNewGeneration::update_counters() { _eden_counters->update_all(); _from_counters->update_all(); _to_counters->update_all(); - _gen_counters->update_all(_virtual_space.committed_size()); + _gen_counters->update_capacity(_virtual_space.committed_size()); } } diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index 2725f1105f1..589e670a2e4 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -368,7 +368,7 @@ void TenuredGeneration::update_promote_stats() { void TenuredGeneration::update_counters() { if (UsePerfData) { _space_counters->update_all(); - _gen_counters->update_all(_virtual_space.committed_size()); + _gen_counters->update_capacity(_virtual_space.committed_size()); } } diff --git a/src/hotspot/share/gc/shared/generationCounters.cpp b/src/hotspot/share/gc/shared/generationCounters.cpp index 4af7b412aea..f6bbc1c2618 100644 --- a/src/hotspot/share/gc/shared/generationCounters.cpp +++ b/src/hotspot/share/gc/shared/generationCounters.cpp @@ -67,7 +67,7 @@ GenerationCounters::~GenerationCounters() { FREE_C_HEAP_ARRAY(char, _name_space); } -void GenerationCounters::update_all(size_t curr_capacity) { +void GenerationCounters::update_capacity(size_t curr_capacity) { _current_size->set_value(curr_capacity); } diff --git a/src/hotspot/share/gc/shared/generationCounters.hpp b/src/hotspot/share/gc/shared/generationCounters.hpp index 50672ab5d74..cb835b44e25 100644 --- a/src/hotspot/share/gc/shared/generationCounters.hpp +++ b/src/hotspot/share/gc/shared/generationCounters.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,7 +52,7 @@ class GenerationCounters: public CHeapObj { ~GenerationCounters(); - void update_all(size_t curr_capacity); + void update_capacity(size_t curr_capacity); const char* name_space() const { return _name_space; } }; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp index 6b72cbdd62b..a2cf404cf55 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMonitoringSupport.cpp @@ -51,7 +51,7 @@ class ShenandoahGenerationCounters : public GenerationCounters { {}; void update_all() { - GenerationCounters::update_all(_heap->capacity()); + GenerationCounters::update_capacity(_heap->capacity()); } }; diff --git a/src/hotspot/share/gc/z/zServiceability.cpp b/src/hotspot/share/gc/z/zServiceability.cpp index 076d310ff71..e5ed99bfccc 100644 --- a/src/hotspot/share/gc/z/zServiceability.cpp +++ b/src/hotspot/share/gc/z/zServiceability.cpp @@ -50,31 +50,11 @@ static ZMemoryUsageInfo compute_memory_usage_info() { return info; } -class ZGenerationCounters : public GenerationCounters { -public: - ZGenerationCounters(const char* name, - int ordinal, - int spaces, - size_t min_capacity, - size_t max_capacity, - size_t curr_capacity) - : GenerationCounters(name, - ordinal, - spaces, - min_capacity, - max_capacity, - curr_capacity) {} - - void update_capacity(size_t capacity) { - update_all(capacity); - } -}; - // Class to expose perf counters used by jstat. class ZServiceabilityCounters : public CHeapObj { private: - ZGenerationCounters _generation_young_counters; - ZGenerationCounters _generation_old_counters; + GenerationCounters _generation_young_counters; + GenerationCounters _generation_old_counters; HSpaceCounters _space_young_counters; HSpaceCounters _space_old_counters; CollectorCounters _minor_collection_counters; From c90c31b07ef64eca65be5018a7757b960552f88a Mon Sep 17 00:00:00 2001 From: Paul Hohensee Date: Wed, 25 Jun 2025 15:52:30 +0000 Subject: [PATCH 179/213] 8279005: sun/tools/jstat tests do not check for test case exit codes after JDK-8245129 Reviewed-by: cjplummer, rkennke --- test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatGcOutput1.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatLineCounts1.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatLineCounts2.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatLineCounts3.sh | 7 ++++++- test/jdk/sun/tools/jstat/jstatLineCounts4.sh | 7 ++++++- test/jdk/sun/tools/jstat/lineCounts1.awk | 2 +- test/jdk/sun/tools/jstat/lineCounts2.awk | 2 +- test/jdk/sun/tools/jstat/lineCounts3.awk | 2 +- test/jdk/sun/tools/jstat/lineCounts4.awk | 2 +- 16 files changed, 76 insertions(+), 16 deletions(-) diff --git a/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh index ccc95be281f..c1908855ea7 100644 --- a/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gccapacity 0 2>&1 | awk -f ${TESTSRC}/gcCapacityOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gccapacity 0 2>&1 | awk -f ${TESTSRC}/gcCapacityOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh index c34a1881673..8652a25fdb7 100644 --- a/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcCauseOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -38,4 +38,9 @@ JSTAT="${TESTJAVA}/bin/jstat" # The UseParallelGC collector does not currently update the gc cause counters. ${JSTAT} ${COMMON_JSTAT_FLAGS} -gccause 0 2>&1 | awk -f ${TESTSRC}/gcCauseOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseSerialGC -gccause 0 2>&1 | awk -f ${TESTSRC}/gcCauseOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh index 66446517c50..b16d0e38d02 100644 --- a/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcMetaCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcmetacapacity 0 2>&1 | awk -f ${TESTSRC}/gcMetaCapacityOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcmetacapacity 0 2>&1 | awk -f ${TESTSRC}/gcMetaCapacityOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh index 44aa864b475..64ce2efd455 100644 --- a/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcNewCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcnewcapacity 0 2>&1 | awk -f ${TESTSRC}/gcNewCapacityOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcnewcapacity 0 2>&1 | awk -f ${TESTSRC}/gcNewCapacityOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh index 0f909f18a9e..b15ec02d2b0 100644 --- a/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcNewOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcnew 0 2>&1 | awk -f ${TESTSRC}/gcNewOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcnew 0 2>&1 | awk -f ${TESTSRC}/gcNewOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh index 433072fddfa..1c13d6f916d 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOldCapacityOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcoldcapacity 0 2>&1 | awk -f ${TESTSRC}/gcOldCapacityOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcoldcapacity 0 2>&1 | awk -f ${TESTSRC}/gcOldCapacityOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh index ee9e30296e0..7f505228b12 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOldOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcold 0 2>&1 | awk -f ${TESTSRC}/gcOldOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcold 0 2>&1 | awk -f ${TESTSRC}/gcOldOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatGcOutput1.sh b/test/jdk/sun/tools/jstat/jstatGcOutput1.sh index 167c53606ad..dfffa2d1a55 100644 --- a/test/jdk/sun/tools/jstat/jstatGcOutput1.sh +++ b/test/jdk/sun/tools/jstat/jstatGcOutput1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gc 0 2>&1 | awk -f ${TESTSRC}/gcOutput1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gc 0 2>&1 | awk -f ${TESTSRC}/gcOutput1.awk diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts1.sh b/test/jdk/sun/tools/jstat/jstatLineCounts1.sh index 75cb051cccf..97338b8e793 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts1.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts1.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil 0 250 5 2>&1 | awk -f ${TESTSRC}/lineCounts1.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil 0 250 5 2>&1 | awk -f ${TESTSRC}/lineCounts1.awk diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts2.sh b/test/jdk/sun/tools/jstat/jstatLineCounts2.sh index 5e0cbafe08d..eab19f3931e 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts2.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts2.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil 0 2>&1 | awk -f ${TESTSRC}/lineCounts2.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil 0 2>&1 | awk -f ${TESTSRC}/lineCounts2.awk diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts3.sh b/test/jdk/sun/tools/jstat/jstatLineCounts3.sh index ef8bbc8ad75..9a769a92464 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts3.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts3.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil -h 10 0 250 10 2>&1 | awk -f ${TESTSRC}/lineCounts3.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil -h 10 0 250 10 2>&1 | awk -f ${TESTSRC}/lineCounts3.awk diff --git a/test/jdk/sun/tools/jstat/jstatLineCounts4.sh b/test/jdk/sun/tools/jstat/jstatLineCounts4.sh index 537172c75e3..817c3b14f62 100644 --- a/test/jdk/sun/tools/jstat/jstatLineCounts4.sh +++ b/test/jdk/sun/tools/jstat/jstatLineCounts4.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,4 +34,9 @@ verify_os JSTAT="${TESTJAVA}/bin/jstat" ${JSTAT} ${COMMON_JSTAT_FLAGS} -gcutil -h 10 0 250 11 2>&1 | awk -f ${TESTSRC}/lineCounts4.awk +RC=$? +if [ $RC -ne 0 ]; then + exit $RC +fi + ${JSTAT} ${COMMON_JSTAT_FLAGS} -J-XX:+UseParallelGC -gcutil -h 10 0 250 11 2>&1 | awk -f ${TESTSRC}/lineCounts4.awk diff --git a/test/jdk/sun/tools/jstat/lineCounts1.awk b/test/jdk/sun/tools/jstat/lineCounts1.awk index d7a7c1d9fb7..1e05506100b 100644 --- a/test/jdk/sun/tools/jstat/lineCounts1.awk +++ b/test/jdk/sun/tools/jstat/lineCounts1.awk @@ -29,7 +29,7 @@ BEGIN { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/test/jdk/sun/tools/jstat/lineCounts2.awk b/test/jdk/sun/tools/jstat/lineCounts2.awk index 201457a3833..4d838c2103e 100644 --- a/test/jdk/sun/tools/jstat/lineCounts2.awk +++ b/test/jdk/sun/tools/jstat/lineCounts2.awk @@ -21,7 +21,7 @@ BEGIN { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/test/jdk/sun/tools/jstat/lineCounts3.awk b/test/jdk/sun/tools/jstat/lineCounts3.awk index 1f155a99ed5..79ae969a47d 100644 --- a/test/jdk/sun/tools/jstat/lineCounts3.awk +++ b/test/jdk/sun/tools/jstat/lineCounts3.awk @@ -39,7 +39,7 @@ BEGIN { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/test/jdk/sun/tools/jstat/lineCounts4.awk b/test/jdk/sun/tools/jstat/lineCounts4.awk index 62aea881e71..7ceb56b9f27 100644 --- a/test/jdk/sun/tools/jstat/lineCounts4.awk +++ b/test/jdk/sun/tools/jstat/lineCounts4.awk @@ -44,7 +44,7 @@ BEGIN { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*([0-9]+|-)[ ]*([0-9]+\.[0-9]+|-)[ ]*[0-9]+\.[0-9]+$/ { if (headerlines == 2) { datalines2++; } From 744727647564ee79349380eb819fefc81ca7dc3a Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 25 Jun 2025 16:02:47 +0000 Subject: [PATCH 180/213] 8360045: StringTokenizer.hasMoreTokens() throws NPE after nextToken(null) Reviewed-by: liach, alanb --- .../classes/java/util/StringTokenizer.java | 4 +- .../NextTokenWithNullDelimTest.java | 45 +++++++++++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 test/jdk/java/util/StringTokenizer/NextTokenWithNullDelimTest.java diff --git a/src/java.base/share/classes/java/util/StringTokenizer.java b/src/java.base/share/classes/java/util/StringTokenizer.java index fae1cd609ad..7b037fff631 100644 --- a/src/java.base/share/classes/java/util/StringTokenizer.java +++ b/src/java.base/share/classes/java/util/StringTokenizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -368,6 +368,8 @@ public String nextToken() { * @throws NullPointerException if delim is {@code null} */ public String nextToken(String delim) { + Objects.requireNonNull(delim); + delimiters = delim; /* delimiter string specified, so set the appropriate flag. */ diff --git a/test/jdk/java/util/StringTokenizer/NextTokenWithNullDelimTest.java b/test/jdk/java/util/StringTokenizer/NextTokenWithNullDelimTest.java new file mode 100644 index 00000000000..9fad96b76e0 --- /dev/null +++ b/test/jdk/java/util/StringTokenizer/NextTokenWithNullDelimTest.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8360045 + * @summary Verify StringTokenizer.nextToken(null) does not alter the + * existing delimiter + * @run junit NextTokenWithNullDelimTest + */ + +import java.util.StringTokenizer; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class NextTokenWithNullDelimTest { + @Test + void testNextTokenWithNullDelim() { + StringTokenizer st = new StringTokenizer("test"); + assertThrows(NullPointerException.class, () -> st.nextToken(null)); + assertDoesNotThrow(st::hasMoreTokens); + } +} From 56c75453cd69e80b9411b4e1794c953998406342 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 25 Jun 2025 18:22:06 +0000 Subject: [PATCH 181/213] 8352565: Add native method implementation of Reference.get() Reviewed-by: vlivanov, tschatzl, lmesnik --- src/hotspot/share/c1/c1_Compiler.cpp | 2 +- src/hotspot/share/c1/c1_GraphBuilder.cpp | 2 +- src/hotspot/share/c1/c1_LIRGenerator.cpp | 6 +- src/hotspot/share/c1/c1_LIRGenerator.hpp | 2 +- src/hotspot/share/classfile/vmIntrinsics.cpp | 4 +- src/hotspot/share/classfile/vmIntrinsics.hpp | 2 +- src/hotspot/share/classfile/vmSymbols.hpp | 2 +- src/hotspot/share/include/jvm.h | 3 + .../share/interpreter/abstractInterpreter.cpp | 6 +- .../share/interpreter/abstractInterpreter.hpp | 2 +- .../templateInterpreterGenerator.cpp | 5 +- .../zero/zeroInterpreterGenerator.cpp | 4 +- src/hotspot/share/opto/c2compiler.cpp | 2 +- src/hotspot/share/opto/compile.cpp | 16 +- src/hotspot/share/opto/library_call.cpp | 6 +- src/hotspot/share/opto/library_call.hpp | 2 +- src/hotspot/share/prims/jvm.cpp | 10 +- .../classes/java/lang/ref/Reference.java | 11 +- .../share/native/libjava/Reference.c | 8 +- .../jtreg/gc/TestNativeReferenceGet.java | 181 ++++++++++++++++++ 20 files changed, 236 insertions(+), 40 deletions(-) create mode 100644 test/hotspot/jtreg/gc/TestNativeReferenceGet.java diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index 8151acd99e0..64a2e6456d8 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -141,7 +141,7 @@ bool Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_arraycopy: case vmIntrinsics::_currentTimeMillis: case vmIntrinsics::_nanoTime: - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: // Use the intrinsic version of Reference.get() so that the value in // the referent field can be registered by the G1 pre-barrier code. // Also to prevent commoning reads from this field across safepoint diff --git a/src/hotspot/share/c1/c1_GraphBuilder.cpp b/src/hotspot/share/c1/c1_GraphBuilder.cpp index c11017fc442..1e4e07360cc 100644 --- a/src/hotspot/share/c1/c1_GraphBuilder.cpp +++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp @@ -3340,7 +3340,7 @@ GraphBuilder::GraphBuilder(Compilation* compilation, IRScope* scope) break; } - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: { { // With java.lang.ref.reference.get() we must go through the diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index 341de0ac0c2..850a196c898 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -1185,7 +1185,7 @@ void LIRGenerator::do_Return(Return* x) { // Example: ref.get() // Combination of LoadField and g1 pre-write barrier -void LIRGenerator::do_Reference_get(Intrinsic* x) { +void LIRGenerator::do_Reference_get0(Intrinsic* x) { const int referent_offset = java_lang_ref_Reference::referent_offset(); @@ -2914,8 +2914,8 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { case vmIntrinsics::_onSpinWait: __ on_spin_wait(); break; - case vmIntrinsics::_Reference_get: - do_Reference_get(x); + case vmIntrinsics::_Reference_get0: + do_Reference_get0(x); break; case vmIntrinsics::_updateCRC32: diff --git a/src/hotspot/share/c1/c1_LIRGenerator.hpp b/src/hotspot/share/c1/c1_LIRGenerator.hpp index e70bbd96189..ec0ea5dc047 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.hpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.hpp @@ -266,7 +266,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void do_CompareAndSwap(Intrinsic* x, ValueType* type); void do_PreconditionsCheckIndex(Intrinsic* x, BasicType type); void do_FPIntrinsics(Intrinsic* x); - void do_Reference_get(Intrinsic* x); + void do_Reference_get0(Intrinsic* x); void do_update_CRC32(Intrinsic* x); void do_update_CRC32C(Intrinsic* x); void do_vectorizedMismatch(Intrinsic* x); diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index baa945cdddf..dd28e1a898c 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -99,7 +99,7 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { case vmIntrinsics::_dpow: case vmIntrinsics::_Preconditions_checkIndex: case vmIntrinsics::_Preconditions_checkLongIndex: - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: case vmIntrinsics::_Continuation_doYield: case vmIntrinsics::_updateCRC32: case vmIntrinsics::_updateBytesCRC32: @@ -244,7 +244,7 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { case vmIntrinsics::_storeFence: case vmIntrinsics::_fullFence: case vmIntrinsics::_countPositives: - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: case vmIntrinsics::_Continuation_doYield: case vmIntrinsics::_Continuation_enterSpecial: case vmIntrinsics::_Continuation_pin: diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index eeefddfedfc..5be372075ed 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -461,7 +461,7 @@ class methodHandle; do_signature(vectorizedMismatch_signature, "(Ljava/lang/Object;JLjava/lang/Object;JII)I") \ \ /* java/lang/ref/Reference */ \ - do_intrinsic(_Reference_get, java_lang_ref_Reference, get_name, void_object_signature, F_R) \ + do_intrinsic(_Reference_get0, java_lang_ref_Reference, get0_name, void_object_signature, F_RN) \ do_intrinsic(_Reference_refersTo0, java_lang_ref_Reference, refersTo0_name, object_boolean_signature, F_RN) \ do_intrinsic(_PhantomReference_refersTo0, java_lang_ref_PhantomReference, refersTo0_name, object_boolean_signature, F_RN) \ do_intrinsic(_Reference_clear0, java_lang_ref_Reference, clear0_name, void_method_signature, F_RN) \ diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index dc9ce61627b..c562e3e6ccf 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -422,7 +422,7 @@ class SerializeClosure; template(sp_name, "sp") \ template(pc_name, "pc") \ template(cs_name, "cs") \ - template(get_name, "get") \ + template(get0_name, "get0") \ template(refersTo0_name, "refersTo0") \ template(clear0_name, "clear0") \ template(put_name, "put") \ diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 73f60765a70..f97374553ca 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -353,6 +353,9 @@ JVM_HasReferencePendingList(JNIEnv *env); JNIEXPORT void JNICALL JVM_WaitForReferencePendingList(JNIEnv *env); +JNIEXPORT jobject JNICALL +JVM_ReferenceGet(JNIEnv *env, jobject ref); + JNIEXPORT jboolean JNICALL JVM_ReferenceRefersTo(JNIEnv *env, jobject ref, jobject o); diff --git a/src/hotspot/share/interpreter/abstractInterpreter.cpp b/src/hotspot/share/interpreter/abstractInterpreter.cpp index 1de7dd824f8..ad39169bca0 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.cpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp @@ -148,7 +148,7 @@ AbstractInterpreter::MethodKind AbstractInterpreter::method_kind(const methodHan case vmIntrinsics::_fmaF: return java_lang_math_fmaF; case vmIntrinsics::_dsqrt: return java_lang_math_sqrt; case vmIntrinsics::_dsqrt_strict: return java_lang_math_sqrt_strict; - case vmIntrinsics::_Reference_get: return java_lang_ref_reference_get; + case vmIntrinsics::_Reference_get0: return java_lang_ref_reference_get0; case vmIntrinsics::_Object_init: if (m->code_size() == 1) { // We need to execute the special return bytecode to check for @@ -210,7 +210,7 @@ vmIntrinsics::ID AbstractInterpreter::method_intrinsic(MethodKind kind) { case java_lang_math_exp : return vmIntrinsics::_dexp; case java_lang_math_fmaD : return vmIntrinsics::_fmaD; case java_lang_math_fmaF : return vmIntrinsics::_fmaF; - case java_lang_ref_reference_get: return vmIntrinsics::_Reference_get; + case java_lang_ref_reference_get0: return vmIntrinsics::_Reference_get0; case java_util_zip_CRC32_update : return vmIntrinsics::_updateCRC32; case java_util_zip_CRC32_updateBytes : return vmIntrinsics::_updateBytesCRC32; @@ -320,7 +320,7 @@ void AbstractInterpreter::print_method_kind(MethodKind kind) { case java_util_zip_CRC32_updateByteBuffer : tty->print("java_util_zip_CRC32_updateByteBuffer"); break; case java_util_zip_CRC32C_updateBytes : tty->print("java_util_zip_CRC32C_updateBytes"); break; case java_util_zip_CRC32C_updateDirectByteBuffer: tty->print("java_util_zip_CRC32C_updateDirectByteByffer"); break; - case java_lang_ref_reference_get : tty->print("java_lang_ref_reference_get"); break; + case java_lang_ref_reference_get0 : tty->print("java_lang_ref_reference_get0"); break; case java_lang_Thread_currentThread : tty->print("java_lang_Thread_currentThread"); break; case java_lang_Float_float16ToFloat : tty->print("java_lang_Float_float16ToFloat"); break; case java_lang_Float_floatToFloat16 : tty->print("java_lang_Float_floatToFloat16"); break; diff --git a/src/hotspot/share/interpreter/abstractInterpreter.hpp b/src/hotspot/share/interpreter/abstractInterpreter.hpp index b6876b3a2da..a3e93aa0a30 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.hpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.hpp @@ -83,7 +83,7 @@ class AbstractInterpreter: AllStatic { java_lang_math_exp, // implementation of java.lang.Math.exp (x) java_lang_math_fmaF, // implementation of java.lang.Math.fma (x, y, z) java_lang_math_fmaD, // implementation of java.lang.Math.fma (x, y, z) - java_lang_ref_reference_get, // implementation of java.lang.ref.Reference.get() + java_lang_ref_reference_get0, // implementation of java.lang.ref.Reference.get() java_util_zip_CRC32_update, // implementation of java.util.zip.CRC32.update() java_util_zip_CRC32_updateBytes, // implementation of java.util.zip.CRC32.updateBytes() java_util_zip_CRC32_updateByteBuffer, // implementation of java.util.zip.CRC32.updateByteBuffer() diff --git a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp index 533c88cce9e..928d1ac9f9c 100644 --- a/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp +++ b/src/hotspot/share/interpreter/templateInterpreterGenerator.cpp @@ -204,7 +204,7 @@ void TemplateInterpreterGenerator::generate_all() { method_entry(java_lang_math_pow ) method_entry(java_lang_math_fmaF ) method_entry(java_lang_math_fmaD ) - method_entry(java_lang_ref_reference_get) + method_entry(java_lang_ref_reference_get0) AbstractInterpreter::initialize_method_handle_entries(); method_entry(java_util_zip_CRC32C_updateBytes) @@ -228,6 +228,7 @@ void TemplateInterpreterGenerator::generate_all() { // entries for `native` methods to use the same address in case // intrinsic is disabled. native_method_entry(java_lang_Thread_currentThread) + native_method_entry(java_lang_ref_reference_get0) native_method_entry(java_util_zip_CRC32_update) native_method_entry(java_util_zip_CRC32_updateBytes) @@ -465,7 +466,7 @@ address TemplateInterpreterGenerator::generate_intrinsic_entry(AbstractInterpret case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break; case Interpreter::java_lang_math_sqrt_strict : entry_point = generate_math_entry(Interpreter::java_lang_math_sqrt); break; - case Interpreter::java_lang_ref_reference_get + case Interpreter::java_lang_ref_reference_get0 : entry_point = generate_Reference_get_entry(); break; case Interpreter::java_util_zip_CRC32_update : entry_point = generate_CRC32_update_entry(); break; diff --git a/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp b/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp index c4eeb3fa840..8fa0835216d 100644 --- a/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp +++ b/src/hotspot/share/interpreter/zero/zeroInterpreterGenerator.cpp @@ -64,7 +64,7 @@ void ZeroInterpreterGenerator::generate_all() { method_entry(java_lang_math_exp ); method_entry(java_lang_math_fmaD ); method_entry(java_lang_math_fmaF ); - method_entry(java_lang_ref_reference_get); + method_entry(java_lang_ref_reference_get0); AbstractInterpreter::initialize_method_handle_entries(); @@ -107,7 +107,7 @@ address ZeroInterpreterGenerator::generate_method_entry( case Interpreter::java_lang_math_exp : // fall thru case Interpreter::java_lang_math_fmaD : // fall thru case Interpreter::java_lang_math_fmaF : entry_point = generate_math_entry(kind); break; - case Interpreter::java_lang_ref_reference_get + case Interpreter::java_lang_ref_reference_get0 : entry_point = generate_Reference_get_entry(); break; default: fatal("unexpected method kind: %d", kind); diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index ea8b6853298..e5b1e131505 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -767,7 +767,7 @@ bool C2Compiler::is_intrinsic_supported(vmIntrinsics::ID id) { case vmIntrinsics::_doubleToRawLongBits: case vmIntrinsics::_doubleToLongBits: case vmIntrinsics::_longBitsToDouble: - case vmIntrinsics::_Reference_get: + case vmIntrinsics::_Reference_get0: case vmIntrinsics::_Reference_refersTo0: case vmIntrinsics::_PhantomReference_refersTo0: case vmIntrinsics::_Reference_clear0: diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index ebc2b28e4ad..4c5f382ceee 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -783,19 +783,9 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, StartNode* s = new StartNode(root(), tf()->domain()); initial_gvn()->set_type_bottom(s); verify_start(s); - if (method()->intrinsic_id() == vmIntrinsics::_Reference_get) { - // With java.lang.ref.reference.get() we must go through the - // intrinsic - even when get() is the root - // method of the compile - so that, if necessary, the value in - // the referent field of the reference object gets recorded by - // the pre-barrier code. - cg = find_intrinsic(method(), false); - } - if (cg == nullptr) { - float past_uses = method()->interpreter_invocation_count(); - float expected_uses = past_uses; - cg = CallGenerator::for_inline(method(), expected_uses); - } + float past_uses = method()->interpreter_invocation_count(); + float expected_uses = past_uses; + cg = CallGenerator::for_inline(method(), expected_uses); } if (failing()) return; if (cg == nullptr) { diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index e454be2b848..94f047dc115 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -564,7 +564,7 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_getCallerClass: return inline_native_Reflection_getCallerClass(); - case vmIntrinsics::_Reference_get: return inline_reference_get(); + case vmIntrinsics::_Reference_get0: return inline_reference_get0(); case vmIntrinsics::_Reference_refersTo0: return inline_reference_refersTo0(false); case vmIntrinsics::_PhantomReference_refersTo0: return inline_reference_refersTo0(true); case vmIntrinsics::_Reference_clear0: return inline_reference_clear0(false); @@ -6923,9 +6923,9 @@ bool LibraryCallKit::inline_updateByteBufferAdler32() { return true; } -//----------------------------inline_reference_get---------------------------- +//----------------------------inline_reference_get0---------------------------- // public T java.lang.ref.Reference.get(); -bool LibraryCallKit::inline_reference_get() { +bool LibraryCallKit::inline_reference_get0() { const int referent_offset = java_lang_ref_Reference::referent_offset(); // Get the argument: diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index 136d0979615..a622eefa248 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -300,7 +300,7 @@ class LibraryCallKit : public GraphKit { bool inline_bitshuffle_methods(vmIntrinsics::ID id); bool inline_compare_unsigned(vmIntrinsics::ID id); bool inline_divmod_methods(vmIntrinsics::ID id); - bool inline_reference_get(); + bool inline_reference_get0(); bool inline_reference_refersTo0(bool is_phantom); bool inline_reference_clear0(bool is_phantom); bool inline_Class_cast(); diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index d669d7bf5ec..1389bf6d602 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -3040,9 +3040,17 @@ JVM_ENTRY(void, JVM_WaitForReferencePendingList(JNIEnv* env)) } JVM_END +JVM_ENTRY(jobject, JVM_ReferenceGet(JNIEnv* env, jobject ref)) + oop ref_oop = JNIHandles::resolve_non_null(ref); + // PhantomReference has its own implementation of get(). + assert(!java_lang_ref_Reference::is_phantom(ref_oop), "precondition"); + oop referent = java_lang_ref_Reference::weak_referent(ref_oop); + return JNIHandles::make_local(THREAD, referent); +JVM_END + JVM_ENTRY(jboolean, JVM_ReferenceRefersTo(JNIEnv* env, jobject ref, jobject o)) oop ref_oop = JNIHandles::resolve_non_null(ref); - // PhantomReference has it's own implementation of refersTo(). + // PhantomReference has its own implementation of refersTo(). // See: JVM_PhantomReferenceRefersTo assert(!java_lang_ref_Reference::is_phantom(ref_oop), "precondition"); oop referent = java_lang_ref_Reference::weak_referent_no_keepalive(ref_oop); diff --git a/src/java.base/share/classes/java/lang/ref/Reference.java b/src/java.base/share/classes/java/lang/ref/Reference.java index c83f197380a..ef2e5e0d0c4 100644 --- a/src/java.base/share/classes/java/lang/ref/Reference.java +++ b/src/java.base/share/classes/java/lang/ref/Reference.java @@ -357,11 +357,18 @@ public void runFinalization() { * {@code null} if this reference object has been cleared * @see #refersTo */ - @IntrinsicCandidate public T get() { - return this.referent; + return get0(); } + /* Implementation of get(). This method exists to avoid making get() all + * of virtual, native, and intrinsic candidate. That could have the + * undesirable effect of having the native method used instead of the + * intrinsic when devirtualization fails. + */ + @IntrinsicCandidate + private native T get0(); + /** * Tests if the referent of this reference object is {@code obj}. * Using a {@code null} {@code obj} returns {@code true} if the diff --git a/src/java.base/share/native/libjava/Reference.c b/src/java.base/share/native/libjava/Reference.c index ce5b34299ad..7fef23c2ba8 100644 --- a/src/java.base/share/native/libjava/Reference.c +++ b/src/java.base/share/native/libjava/Reference.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,12 @@ Java_java_lang_ref_Reference_waitForReferencePendingList(JNIEnv *env, jclass ign JVM_WaitForReferencePendingList(env); } +JNIEXPORT jobject JNICALL +Java_java_lang_ref_Reference_get0(JNIEnv *env, jobject ref) +{ + return JVM_ReferenceGet(env, ref); +} + JNIEXPORT jboolean JNICALL Java_java_lang_ref_Reference_refersTo0(JNIEnv *env, jobject ref, jobject o) { diff --git a/test/hotspot/jtreg/gc/TestNativeReferenceGet.java b/test/hotspot/jtreg/gc/TestNativeReferenceGet.java new file mode 100644 index 00000000000..222d250f79a --- /dev/null +++ b/test/hotspot/jtreg/gc/TestNativeReferenceGet.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc; + +/** + * @test + * @bug 8352565 + * @summary Determine whether the native method implementation of + * Reference.get() works as expected. Disable the intrinsic implementation to + * force use of the native method. + * @library /test/lib + * @modules java.base/java.lang.ref:open + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm + * -Xbootclasspath/a:. + * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:DisableIntrinsic=_Reference_get0 + * gc.TestNativeReferenceGet + */ + +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.List; +import jdk.test.whitebox.WhiteBox; + +public final class TestNativeReferenceGet { + + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + + private static void gcUntilOld(Object o) { + while (!WB.isObjectInOldGen(o)) { + WB.fullGC(); + } + } + + private static final class TestObject { + public final int value; + + public TestObject(int value) { + this.value = value; + } + } + + private static final ReferenceQueue queue = + new ReferenceQueue(); + + private static final class Ref extends WeakReference { + public Ref(TestObject obj) { + super(obj, queue); + } + } + + private static final int NUM_REFS = 100; + + private static List references = null; + private static List referents = null; + + // Create all the objects used by the test, and ensure they are all in the + // old generation. + private static void setup() { + references = new ArrayList(NUM_REFS); + referents = new ArrayList(NUM_REFS); + + for (int i = 0; i < NUM_REFS; ++i) { + TestObject obj = new TestObject(i); + referents.add(obj); + references.add(new Ref(obj)); + } + + gcUntilOld(references); + gcUntilOld(referents); + for (int i = 0; i < NUM_REFS; ++i) { + gcUntilOld(references.get(i)); + gcUntilOld(referents.get(i)); + } + } + + // Discard all the strong references. + private static void dropReferents() { + // Not using List.clear() because it doesn't document null'ing elements. + for (int i = 0; i < NUM_REFS; ++i) { + referents.set(i, null); + } + } + + // Create new strong references from the weak references, by using the + // native method implementation of Reference.get() and recording the value + // in references. + private static void strengthenReferents() { + for (int i = 0; i < NUM_REFS; ++i) { + referents.set(i, references.get(i).get()); + } + } + + private static void check() { + // None of the references should have been cleared and enqueued, + // because we have strong references to all the referents. + try { + while (WB.waitForReferenceProcessing()) {} + } catch (InterruptedException e) { + throw new RuntimeException("Test interrupted"); + } + if (queue.poll() != null) { + throw new RuntimeException("Reference enqueued"); + } + + // Check details of expected state. + for (int i = 0; i < NUM_REFS; ++i) { + Ref reference = (Ref) references.get(i); + TestObject referent = reference.get(); + if (referent == null) { + throw new RuntimeException("Referent not strengthened"); + } else if (referent != referents.get(i)) { + throw new RuntimeException( + "Reference referent differs from saved referent: " + i); + } else if (referent.value != i) { + throw new RuntimeException( + "Referent " + i + " value: " + referent.value); + } + } + } + + private static void testConcurrent() { + System.out.println("Testing concurrent GC"); + try { + WB.concurrentGCAcquireControl(); + dropReferents(); + WB.concurrentGCRunTo(WB.BEFORE_MARKING_COMPLETED); + strengthenReferents(); + WB.concurrentGCRunToIdle(); + check(); + } finally { + WB.concurrentGCReleaseControl(); + } + } + + private static void testNonconcurrent() { + System.out.println("Testing nonconcurrent GC"); + // A GC between clearing and strengthening will result in test failure. + // We try to make that unlikely via this immediately preceeding GC. + WB.fullGC(); + dropReferents(); + strengthenReferents(); + WB.fullGC(); + check(); + } + + public static final void main(String[] args) { + setup(); + if (WB.supportsConcurrentGCBreakpoints()) { + testConcurrent(); + } else { + testNonconcurrent(); + } + } +} From f799cf180a00c6844a994c651852773a519dff2b Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Wed, 25 Jun 2025 18:48:47 +0000 Subject: [PATCH 182/213] 8360303: Remove two unused invoke files Reviewed-by: rriggs, jrose --- .../java/lang/invoke/InvokeDynamic.java | 33 --------------- .../java/lang/invoke/MethodHandleImpl.java | 3 +- .../share/classes/sun/invoke/empty/Empty.java | 40 ------------------- .../classes/sun/invoke/util/VerifyType.java | 5 +-- 4 files changed, 2 insertions(+), 79 deletions(-) delete mode 100644 src/java.base/share/classes/java/lang/invoke/InvokeDynamic.java delete mode 100644 src/java.base/share/classes/sun/invoke/empty/Empty.java diff --git a/src/java.base/share/classes/java/lang/invoke/InvokeDynamic.java b/src/java.base/share/classes/java/lang/invoke/InvokeDynamic.java deleted file mode 100644 index 4668d741bbb..00000000000 --- a/src/java.base/share/classes/java/lang/invoke/InvokeDynamic.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package java.lang.invoke; - -/** - * This is a place-holder class. Some HotSpot implementations need to see it. - */ -final class InvokeDynamic { - private InvokeDynamic() { throw new InternalError(); } // do not instantiate -} diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index a759ec6162e..cf8c9065f2d 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -36,7 +36,6 @@ import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Hidden; import jdk.internal.vm.annotation.Stable; -import sun.invoke.empty.Empty; import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyType; import sun.invoke.util.Wrapper; @@ -983,7 +982,7 @@ static MethodHandle throwException(MethodType type) { return makePairwiseConvert(getFunction(NF_throwException).resolvedHandle(), type, false, true); } - static Empty throwException(T t) throws T { throw t; } + static Void throwException(T t) throws T { throw t; } static MethodHandle[] FAKE_METHOD_HANDLE_INVOKE = new MethodHandle[2]; static MethodHandle fakeMethodHandleInvoke(MemberName method) { diff --git a/src/java.base/share/classes/sun/invoke/empty/Empty.java b/src/java.base/share/classes/sun/invoke/empty/Empty.java deleted file mode 100644 index f75d2b3d016..00000000000 --- a/src/java.base/share/classes/sun/invoke/empty/Empty.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.invoke.empty; - -/** - * An empty class in an empty package. - * Used as a proxy for unprivileged code, since making access checks - * against it will only succeed against public methods in public types. - *

    - * This class also stands (internally to sun.invoke) for the type of a - * value that cannot be produced, because the expression of this type - * always returns abnormally. (Cf. Nothing in the closures proposal.) - * @author jrose - */ -public class Empty { - private Empty() { throw new InternalError(); } -} diff --git a/src/java.base/share/classes/sun/invoke/util/VerifyType.java b/src/java.base/share/classes/sun/invoke/util/VerifyType.java index 7ede11b150e..5ca46cb0b74 100644 --- a/src/java.base/share/classes/sun/invoke/util/VerifyType.java +++ b/src/java.base/share/classes/sun/invoke/util/VerifyType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ package sun.invoke.util; import java.lang.invoke.MethodType; -import sun.invoke.empty.Empty; /** * This class centralizes information about the JVM verifier @@ -93,8 +92,6 @@ public static boolean isNullType(Class type) { // Therefore, it can be safely treated as a value of any // other type that admits null, i.e., a reference type. if (type == Void.class) return true; - // Locally known null-only class: - if (type == Empty.class) return true; return false; } From 52526080bae4fb69172d8c87403510aa4d3c8942 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Wed, 25 Jun 2025 19:21:14 +0000 Subject: [PATCH 183/213] 8225354: serviceability/jvmti/ModuleAwareAgents/ThreadStart failed with Didn't get ThreadStart events in VM early start phase! Reviewed-by: amenkov, cjplummer --- test/hotspot/jtreg/ProblemList.txt | 1 - .../ThreadStart/MAAThreadStart.java | 52 ----- .../ThreadStart/libMAAThreadStart.c | 177 ------------------ 3 files changed, 230 deletions(-) delete mode 100644 test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java delete mode 100644 test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ThreadStart/libMAAThreadStart.c diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 40db325896b..aa262aaf575 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -127,7 +127,6 @@ containers/docker/TestJcmdWithSideCar.java 8341518 linux-x64 serviceability/sa/sadebugd/DebugdConnectTest.java 8239062,8270326 macosx-x64,macosx-aarch64 serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all -serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java 8225354 windows-all serviceability/jvmti/vthread/GetThreadStateMountedTest/GetThreadStateMountedTest.java 8318090,8318729 generic-all serviceability/jvmti/vthread/GetSetLocalTest/GetSetLocalTest.java 8286836 generic-all serviceability/jvmti/vthread/CarrierThreadEventNotification/CarrierThreadEventNotification.java 8333681 generic-all diff --git a/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java b/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java deleted file mode 100644 index 1e973fc5064..00000000000 --- a/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @summary Verify ThreadStart JVMTI event with can_generate_early_vmstart capability - * @requires vm.jvmti - * @run main/othervm/native -agentlib:MAAThreadStart MAAThreadStart - */ - -public class MAAThreadStart { - - static { - try { - System.loadLibrary("MAAThreadStart"); - } catch (UnsatisfiedLinkError ule) { - System.err.println("Could not load MAAThreadStart library"); - System.err.println("java.library.path: " - + System.getProperty("java.library.path")); - throw ule; - } - } - - native static int check(); - - public static void main(String args[]) { - int status = check(); - if (status != 0) { - throw new RuntimeException("Non-zero status returned from the agent: " + status); - } - } -} diff --git a/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ThreadStart/libMAAThreadStart.c b/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ThreadStart/libMAAThreadStart.c deleted file mode 100644 index ea346536e42..00000000000 --- a/test/hotspot/jtreg/serviceability/jvmti/ModuleAwareAgents/ThreadStart/libMAAThreadStart.c +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. - * 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 -#include -#include "jvmti.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef JNI_ENV_ARG - -#ifdef __cplusplus -#define JNI_ENV_ARG(x, y) y -#define JNI_ENV_PTR(x) x -#else -#define JNI_ENV_ARG(x,y) x, y -#define JNI_ENV_PTR(x) (*x) -#endif - -#endif - -#define TranslateError(err) "JVMTI error" - -#define PASSED 0 -#define FAILED 2 - -static const char *EXC_CNAME = "java/lang/Exception"; - -static jvmtiEnv *jvmti = NULL; -static jint result = PASSED; -static jboolean printdump = JNI_FALSE; - -static int thread_start_events_vm_start = 0; - -static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved); - -JNIEXPORT -jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { - return Agent_Initialize(jvm, options, reserved); -} - -JNIEXPORT -jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) { - return Agent_Initialize(jvm, options, reserved); -} - -JNIEXPORT -jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { - return JNI_VERSION_9; -} - -static -jint throw_exc(JNIEnv *env, char *msg) { - jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME)); - - if (exc_class == NULL) { - printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME); - return -1; - } - return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg); -} - - -void JNICALL Callback_ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) { - jvmtiError err; - jvmtiPhase phase; - - err = (*jvmti)->GetPhase(jvmti_env,&phase); - if (err != JVMTI_ERROR_NONE) { - printf("ThreadStart event: GetPhase error: %s (%d)\n", TranslateError(err), err); - result = FAILED; - return; - } - - if (phase == JVMTI_PHASE_START) { - thread_start_events_vm_start++; - } - - if (printdump == JNI_TRUE) { - printf(">>> ThreadStart event: phase(%d)\n", phase); - } -} - -static -jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) { - jint res, size; - jvmtiCapabilities caps; - jvmtiEventCallbacks callbacks; - jvmtiError err; - - if (options != NULL && strcmp(options, "printdump") == 0) { - printdump = JNI_TRUE; - } - - res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti), - JVMTI_VERSION_9); - if (res != JNI_OK || jvmti == NULL) { - printf(" Error: wrong result of a valid call to GetEnv!\n"); - return JNI_ERR; - } - - printf("Enabling following capability: can_generate_early_vmstart\n"); - memset(&caps, 0, sizeof(caps)); - caps.can_generate_early_vmstart = 1; - - err = (*jvmti)->AddCapabilities(jvmti, &caps); - if (err != JVMTI_ERROR_NONE) { - printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err); - return JNI_ERR; - } - - size = (jint)sizeof(callbacks); - - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.ThreadStart = Callback_ThreadStart; - - err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size); - if (err != JVMTI_ERROR_NONE) { - printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err); - return JNI_ERR; - } - - err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, NULL); - if (err != JVMTI_ERROR_NONE) { - printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err); - return JNI_ERR; - } - - return JNI_OK; -} - -JNIEXPORT jint JNICALL -Java_MAAThreadStart_check(JNIEnv *env, jclass cls) { - jobject loader = NULL; - - if (jvmti == NULL) { - throw_exc(env, "JVMTI client was not properly loaded!\n"); - return FAILED; - } - - /* - * Expecting that ThreadStart events are sent during VM Start phase when - * can_generate_early_vmstart capability is enabled. - */ - if (thread_start_events_vm_start == 0) { - throw_exc(env, "Didn't get ThreadStart events in VM early start phase!\n"); - return FAILED; - } - - return result; -} - -#ifdef __cplusplus -} -#endif From cf75f1f9c6d2bc70c7133cb81c73a0ce0946dff9 Mon Sep 17 00:00:00 2001 From: Dean Long Date: Wed, 25 Jun 2025 19:25:34 +0000 Subject: [PATCH 184/213] 8358821: patch_verified_entry causes problems, use nmethod entry barriers instead Co-authored-by: Martin Doerr Co-authored-by: Amit Kumar Reviewed-by: mdoerr, eosterlund --- src/hotspot/cpu/aarch64/aarch64.ad | 4 -- .../cpu/aarch64/nativeInst_aarch64.cpp | 34 --------- .../cpu/aarch64/nativeInst_aarch64.hpp | 4 -- .../arm/gc/shared/barrierSetAssembler_arm.cpp | 5 +- src/hotspot/cpu/arm/nativeInst_arm_32.cpp | 10 --- src/hotspot/cpu/arm/nativeInst_arm_32.hpp | 10 +-- src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp | 1 - src/hotspot/cpu/ppc/nativeInst_ppc.cpp | 35 +-------- src/hotspot/cpu/ppc/nativeInst_ppc.hpp | 17 +---- src/hotspot/cpu/ppc/ppc.ad | 7 +- src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 57 --------------- src/hotspot/cpu/riscv/nativeInst_riscv.hpp | 6 +- src/hotspot/cpu/riscv/riscv.ad | 11 +-- .../gc/shared/barrierSetAssembler_s390.cpp | 2 +- src/hotspot/cpu/s390/nativeInst_s390.cpp | 34 --------- src/hotspot/cpu/s390/nativeInst_s390.hpp | 10 +-- src/hotspot/cpu/s390/stubGenerator_s390.cpp | 2 +- src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp | 10 --- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 10 +-- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 13 ---- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 2 - src/hotspot/cpu/x86/nativeInst_x86.cpp | 49 ------------- src/hotspot/cpu/x86/nativeInst_x86.hpp | 3 - src/hotspot/cpu/zero/nativeInst_zero.cpp | 44 ------------ src/hotspot/cpu/zero/nativeInst_zero.hpp | 10 +-- src/hotspot/os/windows/os_windows.cpp | 13 ---- src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp | 11 +-- .../os_cpu/bsd_aarch64/os_bsd_aarch64.cpp | 9 +-- .../os_cpu/linux_aarch64/os_linux_aarch64.cpp | 9 +-- src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp | 5 -- src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp | 10 +-- .../os_cpu/linux_riscv/os_linux_riscv.cpp | 9 +-- .../os_cpu/linux_s390/os_linux_s390.cpp | 10 +-- src/hotspot/share/code/nmethod.cpp | 29 +------- .../share/gc/shared/barrierSetNMethod.cpp | 71 ++++++++++++++----- .../share/gc/shared/barrierSetNMethod.hpp | 24 +++++-- .../gc/shenandoah/shenandoahCodeRoots.cpp | 2 +- src/hotspot/share/gc/z/zBarrierSetNMethod.cpp | 33 +++++++++ src/hotspot/share/gc/z/zBarrierSetNMethod.hpp | 12 ++++ src/hotspot/share/gc/z/zMark.cpp | 2 +- src/hotspot/share/gc/z/zNMethod.cpp | 7 +- src/hotspot/share/runtime/mutexLocker.cpp | 3 + src/hotspot/share/runtime/mutexLocker.hpp | 1 + 43 files changed, 144 insertions(+), 506 deletions(-) delete mode 100644 src/hotspot/cpu/zero/nativeInst_zero.cpp diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 58567e9f713..456712cf8da 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1765,10 +1765,6 @@ void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { // n.b. frame size includes space for return pc and rfp const int framesize = C->output()->frame_size_in_bytes(); - // insert a nop at the start of the prolog so we can patch in a - // branch if we need to invalidate the method later - __ nop(); - if (C->clinit_barrier_on_entry()) { assert(!C->method()->holder()->is_not_initialized(), "initialization should have been started"); diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp index 0b05b4ac3e5..5a7fececafa 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.cpp @@ -212,11 +212,6 @@ void NativeMovRegMem::verify() { void NativeJump::verify() { ; } - -void NativeJump::check_verified_entry_alignment(address entry, address verified_entry) { -} - - address NativeJump::jump_destination() const { address dest = MacroAssembler::target_addr_for_insn_or_null(instruction_address()); @@ -345,10 +340,6 @@ bool NativeInstruction::is_movk() { return Instruction_aarch64::extract(int_at(0), 30, 23) == 0b11100101; } -bool NativeInstruction::is_sigill_not_entrant() { - return uint_at(0) == 0xd4bbd5a1; // dcps1 #0xdead -} - void NativeIllegalInstruction::insert(address code_pos) { *(juint*)code_pos = 0xd4bbd5a1; // dcps1 #0xdead } @@ -359,31 +350,6 @@ bool NativeInstruction::is_stop() { //------------------------------------------------------------------- -// MT-safe inserting of a jump over a jump or a nop (used by -// nmethod::make_not_entrant) - -void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) { - - assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch"); - assert(nativeInstruction_at(verified_entry)->is_jump_or_nop() - || nativeInstruction_at(verified_entry)->is_sigill_not_entrant(), - "Aarch64 cannot replace non-jump with jump"); - - // Patch this nmethod atomically. - if (Assembler::reachable_from_branch_at(verified_entry, dest)) { - ptrdiff_t disp = dest - verified_entry; - guarantee(disp < 1 << 27 && disp > - (1 << 27), "branch overflow"); - - unsigned int insn = (0b000101 << 26) | ((disp >> 2) & 0x3ffffff); - *(unsigned int*)verified_entry = insn; - } else { - // We use an illegal instruction for marking a method as not_entrant. - NativeIllegalInstruction::insert(verified_entry); - } - - ICache::invalidate_range(verified_entry, instruction_size); -} - void NativeGeneralJump::verify() { } // MT-safe patching of a long jump instruction. diff --git a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp index 9b9b83e38b8..df5d97c2376 100644 --- a/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/nativeInst_aarch64.hpp @@ -83,7 +83,6 @@ class NativeInstruction { bool is_safepoint_poll(); bool is_movz(); bool is_movk(); - bool is_sigill_not_entrant(); bool is_stop(); protected: @@ -360,9 +359,6 @@ class NativeJump: public NativeInstruction { // Insertion of native jump instruction static void insert(address code_pos, address entry); - // MT-safe insertion of native jump at verified method entry - static void check_verified_entry_alignment(address entry, address verified_entry); - static void patch_verified_entry(address entry, address verified_entry, address dest); }; inline NativeJump* nativeJump_at(address address) { diff --git a/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp b/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp index 4492c9da33e..029e5131a84 100644 --- a/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/gc/shared/barrierSetAssembler_arm.cpp @@ -193,10 +193,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) { __ bind(guard); // nmethod guard value. Skipped over in common case. - // - // Put a debug value to make any offsets skew - // clearly visible in coredump - __ emit_int32(0xDEADBEAF); + __ emit_int32(0); // initial armed value, will be reset later __ bind(skip); __ block_comment("nmethod_barrier end"); diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp index 2caf2d7587e..232294b246a 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.cpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.cpp @@ -282,16 +282,6 @@ void NativeMovConstReg::set_pc_relative_offset(address addr, address pc) { } } -void RawNativeJump::check_verified_entry_alignment(address entry, address verified_entry) { -} - -void RawNativeJump::patch_verified_entry(address entry, address verified_entry, address dest) { - assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "should be"); - int *a = (int *)verified_entry; - a[0] = not_entrant_illegal_instruction; // always illegal - ICache::invalidate_range((address)&a[0], sizeof a[0]); -} - void NativeGeneralJump::insert_unconditional(address code_pos, address entry) { int offset = (int)(entry - code_pos - 8); assert(offset < 0x2000000 && offset > -0x2000000, "encoding constraint"); diff --git a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp index e26c23cd983..ee856bcfe60 100644 --- a/src/hotspot/cpu/arm/nativeInst_arm_32.hpp +++ b/src/hotspot/cpu/arm/nativeInst_arm_32.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,10 +61,6 @@ class RawNativeInstruction { instr_fld_fst = 0xd0 }; - // illegal instruction used by NativeJump::patch_verified_entry - // permanently undefined (UDF): 0xe << 28 | 0b1111111 << 20 | 0b1111 << 4 - static const int not_entrant_illegal_instruction = 0xe7f000f0; - static int decode_rotated_imm12(int encoding) { int base = encoding & 0xff; int right_rotation = (encoding & 0xf00) >> 7; @@ -274,10 +270,6 @@ class RawNativeJump: public NativeInstruction { } } - static void check_verified_entry_alignment(address entry, address verified_entry); - - static void patch_verified_entry(address entry, address verified_entry, address dest); - }; inline RawNativeJump* rawNativeJump_at(address address) { diff --git a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp index 77d3653aefd..02e069b6be1 100644 --- a/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_MacroAssembler_ppc.cpp @@ -46,7 +46,6 @@ void C1_MacroAssembler::explicit_null_check(Register base) { void C1_MacroAssembler::build_frame(int frame_size_in_bytes, int bang_size_in_bytes) { - // Avoid stack bang as first instruction. It may get overwritten by patch_verified_entry. const Register return_pc = R20; mflr(return_pc); diff --git a/src/hotspot/cpu/ppc/nativeInst_ppc.cpp b/src/hotspot/cpu/ppc/nativeInst_ppc.cpp index 1114da60d2b..ca492329729 100644 --- a/src/hotspot/cpu/ppc/nativeInst_ppc.cpp +++ b/src/hotspot/cpu/ppc/nativeInst_ppc.cpp @@ -39,18 +39,6 @@ #include "c1/c1_Runtime1.hpp" #endif -// We use an illtrap for marking a method as not_entrant -// Work around a C++ compiler bug which changes 'this' -bool NativeInstruction::is_sigill_not_entrant_at(address addr) { - if (!Assembler::is_illtrap(addr)) return false; - CodeBlob* cb = CodeCache::find_blob(addr); - if (cb == nullptr || !cb->is_nmethod()) return false; - nmethod *nm = (nmethod *)cb; - // This method is not_entrant iff the illtrap instruction is - // located at the verified entry point. - return nm->verified_entry_point() == addr; -} - #ifdef ASSERT void NativeInstruction::verify() { // Make sure code pattern is actually an instruction address. @@ -331,25 +319,6 @@ void NativeMovConstReg::verify() { } #endif // ASSERT -void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) { - ResourceMark rm; - int code_size = 1 * BytesPerInstWord; - CodeBuffer cb(verified_entry, code_size + 1); - MacroAssembler* a = new MacroAssembler(&cb); -#ifdef COMPILER2 - assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch"); -#endif - // Patch this nmethod atomically. Always use illtrap/trap in debug build. - if (DEBUG_ONLY(false &&) a->is_within_range_of_b(dest, a->pc())) { - a->b(dest); - } else { - // The signal handler will continue at dest=OptoRuntime::handle_wrong_method_stub(). - // We use an illtrap for marking a method as not_entrant. - a->illtrap(); - } - ICache::ppc64_flush_icache_bytes(verified_entry, code_size); -} - #ifdef ASSERT void NativeJump::verify() { address addr = addr_at(0); @@ -462,9 +431,7 @@ bool NativeDeoptInstruction::is_deopt_at(address code_pos) { if (!Assembler::is_illtrap(code_pos)) return false; CodeBlob* cb = CodeCache::find_blob(code_pos); if (cb == nullptr || !cb->is_nmethod()) return false; - nmethod *nm = (nmethod *)cb; - // see NativeInstruction::is_sigill_not_entrant_at() - return nm->verified_entry_point() != code_pos; + return true; } // Inserts an instruction which is specified to cause a SIGILL at a given pc diff --git a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp index f4d570116a8..38126ec858d 100644 --- a/src/hotspot/cpu/ppc/nativeInst_ppc.hpp +++ b/src/hotspot/cpu/ppc/nativeInst_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -69,13 +69,6 @@ class NativeInstruction { return MacroAssembler::tdi_get_si16(long_at(0), Assembler::traptoUnconditional, 0); } - // We use an illtrap for marking a method as not_entrant. - bool is_sigill_not_entrant() { - // Work around a C++ compiler bug which changes 'this'. - return NativeInstruction::is_sigill_not_entrant_at(addr_at(0)); - } - static bool is_sigill_not_entrant_at(address addr); - #ifdef COMPILER2 // SIGTRAP-based implicit range checks bool is_sigtrap_range_check() { @@ -328,15 +321,7 @@ class NativeJump: public NativeInstruction { } } - // MT-safe insertion of native jump at verified method entry - static void patch_verified_entry(address entry, address verified_entry, address dest); - void verify() NOT_DEBUG_RETURN; - - static void check_verified_entry_alignment(address entry, address verified_entry) { - // We just patch one instruction on ppc64, so the jump doesn't have to - // be aligned. Nothing to do here. - } }; // Instantiates a NativeJump object starting at the given instruction diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 80a39610a4c..5f85ff96664 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -1493,12 +1493,7 @@ void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { const Register toc_temp = R23; assert_different_registers(R11, return_pc, callers_sp, push_frame_temp, toc_temp); - if (method_is_frameless) { - // Add nop at beginning of all frameless methods to prevent any - // oop instructions from getting overwritten by make_not_entrant - // (patching attempt would fail). - __ nop(); - } else { + if (!method_is_frameless) { // Get return pc. __ mflr(return_pc); } diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index 31947b520d0..3834a0d3d3d 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -356,18 +356,6 @@ void NativeMovRegMem::verify() { void NativeJump::verify() { } - -void NativeJump::check_verified_entry_alignment(address entry, address verified_entry) { - // Patching to not_entrant can happen while activations of the method are - // in use. The patching in that instance must happen only when certain - // alignment restrictions are true. These guarantees check those - // conditions. - - // Must be 4 bytes aligned - MacroAssembler::assert_alignment(verified_entry); -} - - address NativeJump::jump_destination() const { address dest = MacroAssembler::target_addr_for_insn(instruction_address()); @@ -420,12 +408,6 @@ bool NativeInstruction::is_safepoint_poll() { return MacroAssembler::is_lwu_to_zr(address(this)); } -// A 16-bit instruction with all bits ones is permanently reserved as an illegal instruction. -bool NativeInstruction::is_sigill_not_entrant() { - // jvmci - return uint_at(0) == 0xffffffff; -} - void NativeIllegalInstruction::insert(address code_pos) { assert_cond(code_pos != nullptr); Assembler::sd_instr(code_pos, 0xffffffff); // all bits ones is permanently reserved as an illegal instruction @@ -437,45 +419,6 @@ bool NativeInstruction::is_stop() { //------------------------------------------------------------------- -// MT-safe inserting of a jump over a jump or a nop (used by -// nmethod::make_not_entrant) - -void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) { - - assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch"); - - assert(nativeInstruction_at(verified_entry)->is_jump_or_nop() || - nativeInstruction_at(verified_entry)->is_sigill_not_entrant(), - "riscv cannot replace non-jump with jump"); - - check_verified_entry_alignment(entry, verified_entry); - - // Patch this nmethod atomically. - if (Assembler::reachable_from_branch_at(verified_entry, dest)) { - ptrdiff_t offset = dest - verified_entry; - guarantee(Assembler::is_simm21(offset) && ((offset % 2) == 0), - "offset is too large to be patched in one jal instruction."); // 1M - - uint32_t insn = 0; - address pInsn = (address)&insn; - Assembler::patch(pInsn, 31, 31, (offset >> 20) & 0x1); - Assembler::patch(pInsn, 30, 21, (offset >> 1) & 0x3ff); - Assembler::patch(pInsn, 20, 20, (offset >> 11) & 0x1); - Assembler::patch(pInsn, 19, 12, (offset >> 12) & 0xff); - Assembler::patch(pInsn, 11, 7, 0); // zero, no link jump - Assembler::patch(pInsn, 6, 0, 0b1101111); // j, (jal x0 offset) - Assembler::sd_instr(verified_entry, insn); - } else { - // We use an illegal instruction for marking a method as - // not_entrant. - NativeIllegalInstruction::insert(verified_entry); - } - - ICache::invalidate_range(verified_entry, instruction_size); -} - -//------------------------------------------------------------------- - void NativeGeneralJump::insert_unconditional(address code_pos, address entry) { CodeBuffer cb(code_pos, instruction_size); MacroAssembler a(&cb); diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index d8f5fa57816..1598dfb8398 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2018, 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. @@ -74,7 +74,6 @@ class NativeInstruction { bool is_nop() const; bool is_jump_or_nop(); bool is_safepoint_poll(); - bool is_sigill_not_entrant(); bool is_stop(); protected: @@ -274,9 +273,6 @@ class NativeJump: public NativeInstruction { // Insertion of native jump instruction static void insert(address code_pos, address entry); - // MT-safe insertion of native jump at verified method entry - static void check_verified_entry_alignment(address entry, address verified_entry); - static void patch_verified_entry(address entry, address verified_entry, address dest); }; inline NativeJump* nativeJump_at(address addr) { diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index c2f44986658..716ffae27b5 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1368,14 +1368,6 @@ void MachPrologNode::emit(C2_MacroAssembler *masm, PhaseRegAlloc *ra_) const { // n.b. frame size includes space for return pc and fp const int framesize = C->output()->frame_size_in_bytes(); - // insert a nop at the start of the prolog so we can patch in a - // branch if we need to invalidate the method later - { - Assembler::IncompressibleScope scope(masm); // keep the nop as 4 bytes for patching. - MacroAssembler::assert_alignment(__ pc()); - __ nop(); // 4 bytes - } - assert_cond(C != nullptr); if (C->clinit_barrier_on_entry()) { @@ -1804,7 +1796,6 @@ void MachUEPNode::emit(C2_MacroAssembler* masm, PhaseRegAlloc* ra_) const // This is the unverified entry point. __ ic_check(CodeEntryAlignment); - // Verified entry point must be properly 4 bytes aligned for patching by NativeJump::patch_verified_entry(). // ic_check() aligns to CodeEntryAlignment >= InteriorEntryAlignment(min 16) > NativeInstruction::instruction_size(4). assert(((__ offset()) % CodeEntryAlignment) == 0, "Misaligned verified entry point"); } @@ -8199,7 +8190,7 @@ instruct unnecessary_membar_volatile_rvtso() %{ ins_cost(0); size(0); - + format %{ "#@unnecessary_membar_volatile_rvtso (unnecessary so empty encoding)" %} ins_encode %{ __ block_comment("unnecessary_membar_volatile_rvtso"); diff --git a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp index e78906708af..2d663061aec 100644 --- a/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/gc/shared/barrierSetAssembler_s390.cpp @@ -180,7 +180,7 @@ void BarrierSetAssembler::nmethod_entry_barrier(MacroAssembler* masm) { __ z_lg(Z_R0_scratch, in_bytes(bs_nm->thread_disarmed_guard_value_offset()), Z_thread); // 6 bytes // Compare to current patched value: - __ z_cfi(Z_R0_scratch, /* to be patched */ -1); // 6 bytes (2 + 4 byte imm val) + __ z_cfi(Z_R0_scratch, /* to be patched */ 0); // 6 bytes (2 + 4 byte imm val) // Conditional Jump __ z_larl(Z_R14, (Assembler::instr_len((unsigned long)LARL_ZOPC) + Assembler::instr_len((unsigned long)BCR_ZOPC)) / 2); // 6 bytes diff --git a/src/hotspot/cpu/s390/nativeInst_s390.cpp b/src/hotspot/cpu/s390/nativeInst_s390.cpp index 9990c225a89..546f8b13397 100644 --- a/src/hotspot/cpu/s390/nativeInst_s390.cpp +++ b/src/hotspot/cpu/s390/nativeInst_s390.cpp @@ -167,27 +167,6 @@ bool NativeInstruction::is_illegal() { return halfword_at(-2) == illegal_instruction(); } -// We use an illtrap for marking a method as not_entrant. -bool NativeInstruction::is_sigill_not_entrant() { - if (!is_illegal()) return false; // Just a quick path. - - // One-sided error of is_illegal tolerable here - // (see implementation of is_illegal() for details). - - CodeBlob* cb = CodeCache::find_blob(addr_at(0)); - if (cb == nullptr || !cb->is_nmethod()) { - return false; - } - - nmethod *nm = (nmethod *)cb; - // This method is not_entrant if the illtrap instruction - // is located at the verified entry point. - // BE AWARE: the current pc (this) points to the instruction after the - // "illtrap" location. - address sig_addr = ((address) this) - 2; - return nm->verified_entry_point() == sig_addr; -} - bool NativeInstruction::is_jump() { unsigned long inst; Assembler::get_instruction((address)this, &inst); @@ -620,19 +599,6 @@ void NativeJump::verify() { fatal("this is not a `NativeJump' site"); } -// Patch atomically with an illtrap. -void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) { - ResourceMark rm; - int code_size = 2; - CodeBuffer cb(verified_entry, code_size + 1); - MacroAssembler* a = new MacroAssembler(&cb); -#ifdef COMPILER2 - assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "expected fixed destination of patch"); -#endif - a->z_illtrap(); - ICache::invalidate_range(verified_entry, code_size); -} - #undef LUCY_DBG //------------------------------------- diff --git a/src/hotspot/cpu/s390/nativeInst_s390.hpp b/src/hotspot/cpu/s390/nativeInst_s390.hpp index fcae833769f..16400df3f26 100644 --- a/src/hotspot/cpu/s390/nativeInst_s390.hpp +++ b/src/hotspot/cpu/s390/nativeInst_s390.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2016, 2024 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -85,9 +85,6 @@ class NativeInstruction { // Bcrl is currently the only accepted instruction here. bool is_jump(); - // We use an illtrap for marking a method as not_entrant. - bool is_sigill_not_entrant(); - bool is_safepoint_poll() { // Is the current instruction a POTENTIAL read access to the polling page? // The instruction's current arguments are not checked! @@ -609,11 +606,6 @@ class NativeJump: public NativeInstruction { // Insertion of native jump instruction. static void insert(address code_pos, address entry); - - // MT-safe insertion of native jump at verified method entry. - static void check_verified_entry_alignment(address entry, address verified_entry) { } - - static void patch_verified_entry(address entry, address verified_entry, address dest); }; //------------------------------------- diff --git a/src/hotspot/cpu/s390/stubGenerator_s390.cpp b/src/hotspot/cpu/s390/stubGenerator_s390.cpp index d1c794002e7..45a9e02ac27 100644 --- a/src/hotspot/cpu/s390/stubGenerator_s390.cpp +++ b/src/hotspot/cpu/s390/stubGenerator_s390.cpp @@ -3197,7 +3197,7 @@ class StubGenerator: public StubCodeGenerator { // VM-Call: BarrierSetNMethod::nmethod_stub_entry_barrier(address* return_address_ptr) __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSetNMethod::nmethod_stub_entry_barrier)); - __ z_ltr(Z_R0_scratch, Z_RET); + __ z_ltr(Z_RET, Z_RET); // VM-Call Epilogue __ restore_volatile_regs(Z_SP, frame::z_abi_160_size, true, false); diff --git a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp index 684347e35fa..cde429b0383 100644 --- a/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c1_MacroAssembler_x86.cpp @@ -325,16 +325,6 @@ void C1_MacroAssembler::remove_frame(int frame_size_in_bytes) { void C1_MacroAssembler::verified_entry(bool breakAtEntry) { - if (breakAtEntry) { - // Verified Entry first instruction should be 5 bytes long for correct - // patching by patch_verified_entry(). - // - // Breakpoint has one byte first instruction. - // Also first instruction will be one byte "push(rbp)" if stack banging - // code is not generated (see build_frame() above). - // For all these cases generate long instruction first. - fat_nop(); - } if (breakAtEntry) int3(); // build frame } diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 4317bb3d018..d9a9ef0de3b 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -50,13 +50,6 @@ // C2 compiled method's prolog code. void C2_MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b, bool is_stub) { - - // WARNING: Initial instruction MUST be 5 bytes or longer so that - // NativeJump::patch_verified_entry will be able to patch out the entry - // code safely. The push to verify stack depth is ok at 5 bytes, - // the frame allocation can be either 3 or 6 bytes. So if we don't do - // stack bang then we must use the 6 byte frame allocation even if - // we have no frame. :-( assert(stack_bang_size >= framesize || stack_bang_size <= 0, "stack bang size incorrect"); assert((framesize & (StackAlignmentInBytes-1)) == 0, "frame size not aligned"); @@ -87,8 +80,7 @@ void C2_MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool subptr(rsp, framesize); } } else { - // Create frame (force generation of a 4 byte immediate value) - subptr_imm32(rsp, framesize); + subptr(rsp, framesize); // Save RBP register now. framesize -= wordSize; diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 803bce48945..c401863d7cd 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -1621,19 +1621,6 @@ void MacroAssembler::post_call_nop() { emit_int32(0x00); } -// A 5 byte nop that is safe for patching (see patch_verified_entry) -void MacroAssembler::fat_nop() { - if (UseAddressNop) { - addr_nop_5(); - } else { - emit_int8((uint8_t)0x26); // es: - emit_int8((uint8_t)0x2e); // cs: - emit_int8((uint8_t)0x64); // fs: - emit_int8((uint8_t)0x65); // gs: - emit_int8((uint8_t)0x90); - } -} - void MacroAssembler::mulpd(XMMRegister dst, AddressLiteral src, Register rscratch) { assert(rscratch != noreg || always_reachable(src), "missing"); if (reachable(src)) { diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index f7ac6fb4297..d75c9b624fd 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -209,8 +209,6 @@ class MacroAssembler: public Assembler { void align(uint modulus, uint target); void post_call_nop(); - // A 5 byte nop that is safe for patching (see patch_verified_entry) - void fat_nop(); // Stack frame creation/removal void enter(); diff --git a/src/hotspot/cpu/x86/nativeInst_x86.cpp b/src/hotspot/cpu/x86/nativeInst_x86.cpp index c3345be2172..aad1f77e173 100644 --- a/src/hotspot/cpu/x86/nativeInst_x86.cpp +++ b/src/hotspot/cpu/x86/nativeInst_x86.cpp @@ -336,55 +336,6 @@ void NativeJump::insert(address code_pos, address entry) { ICache::invalidate_range(code_pos, instruction_size); } -void NativeJump::check_verified_entry_alignment(address entry, address verified_entry) { - // Patching to not_entrant can happen while activations of the method are - // in use. The patching in that instance must happen only when certain - // alignment restrictions are true. These guarantees check those - // conditions. - const int linesize = 64; - - // Must be wordSize aligned - guarantee(((uintptr_t) verified_entry & (wordSize -1)) == 0, - "illegal address for code patching 2"); - // First 5 bytes must be within the same cache line - 4827828 - guarantee((uintptr_t) verified_entry / linesize == - ((uintptr_t) verified_entry + 4) / linesize, - "illegal address for code patching 3"); -} - - -// MT safe inserting of a jump over an unknown instruction sequence (used by nmethod::make_not_entrant) -// The problem: jmp is a 5-byte instruction. Atomic write can be only with 4 bytes. -// First patches the first word atomically to be a jump to itself. -// Then patches the last byte and then atomically patches the first word (4-bytes), -// thus inserting the desired jump -// This code is mt-safe with the following conditions: entry point is 4 byte aligned, -// entry point is in same cache line as unverified entry point, and the instruction being -// patched is >= 5 byte (size of patch). -// -// In C2 the 5+ byte sized instruction is enforced by code in MachPrologNode::emit. -// In C1 the restriction is enforced by CodeEmitter::method_entry -// In JVMCI, the restriction is enforced by HotSpotFrameContext.enter(...) -// -void NativeJump::patch_verified_entry(address entry, address verified_entry, address dest) { - // complete jump instruction (to be inserted) is in code_buffer; - union { - jlong cb_long; - unsigned char code_buffer[8]; - } u; - - u.cb_long = *(jlong *)verified_entry; - - intptr_t disp = (intptr_t)dest - ((intptr_t)verified_entry + 1 + 4); - guarantee(disp == (intptr_t)(int32_t)disp, "must be 32-bit offset"); - - u.code_buffer[0] = instruction_code; - *(int32_t*)(u.code_buffer + 1) = (int32_t)disp; - - Atomic::store((jlong *) verified_entry, u.cb_long); - ICache::invalidate_range(verified_entry, 8); -} - void NativeIllegalInstruction::insert(address code_pos) { assert(NativeIllegalInstruction::instruction_size == sizeof(short), "right address unit for update"); *(short *)code_pos = instruction_code; diff --git a/src/hotspot/cpu/x86/nativeInst_x86.hpp b/src/hotspot/cpu/x86/nativeInst_x86.hpp index b2448cb99fd..3e767006480 100644 --- a/src/hotspot/cpu/x86/nativeInst_x86.hpp +++ b/src/hotspot/cpu/x86/nativeInst_x86.hpp @@ -445,9 +445,6 @@ class NativeJump: public NativeInstruction { // Insertion of native jump instruction static void insert(address code_pos, address entry); - // MT-safe insertion of native jump at verified method entry - static void check_verified_entry_alignment(address entry, address verified_entry); - static void patch_verified_entry(address entry, address verified_entry, address dest); }; inline NativeJump* nativeJump_at(address address) { diff --git a/src/hotspot/cpu/zero/nativeInst_zero.cpp b/src/hotspot/cpu/zero/nativeInst_zero.cpp deleted file mode 100644 index 0d2747f7fa6..00000000000 --- a/src/hotspot/cpu/zero/nativeInst_zero.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright 2008 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 - * 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 "asm/assembler.inline.hpp" -#include "entry_zero.hpp" -#include "interpreter/zero/zeroInterpreter.hpp" -#include "nativeInst_zero.hpp" -#include "runtime/sharedRuntime.hpp" - -// This method is called by nmethod::make_not_entrant to -// insert a jump to SharedRuntime::get_handle_wrong_method_stub() -// (dest) at the start of a compiled method (verified_entry) to avoid -// a race where a method is invoked while being made non-entrant. - -void NativeJump::patch_verified_entry(address entry, - address verified_entry, - address dest) { - assert(dest == SharedRuntime::get_handle_wrong_method_stub(), "should be"); - - ((ZeroEntry*) verified_entry)->set_entry_point( - (address) ZeroInterpreter::normal_entry); -} diff --git a/src/hotspot/cpu/zero/nativeInst_zero.hpp b/src/hotspot/cpu/zero/nativeInst_zero.hpp index fd8f03f1a59..399a8e96bc3 100644 --- a/src/hotspot/cpu/zero/nativeInst_zero.hpp +++ b/src/hotspot/cpu/zero/nativeInst_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright 2007 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -177,14 +177,6 @@ class NativeJump : public NativeInstruction { void set_jump_destination(address dest) { ShouldNotCallThis(); } - - static void check_verified_entry_alignment(address entry, - address verified_entry) { - } - - static void patch_verified_entry(address entry, - address verified_entry, - address dest); }; inline NativeJump* nativeJump_at(address address) { diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 9e536d2df97..24969683a1f 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2752,19 +2752,6 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { } } -#ifdef _M_ARM64 - if (in_java && - (exception_code == EXCEPTION_ILLEGAL_INSTRUCTION || - exception_code == EXCEPTION_ILLEGAL_INSTRUCTION_2)) { - if (nativeInstruction_at(pc)->is_sigill_not_entrant()) { - if (TraceTraps) { - tty->print_cr("trap: not_entrant"); - } - return Handle_Exception(exceptionInfo, SharedRuntime::get_handle_wrong_method_stub()); - } - } -#endif - if (in_java) { switch (exception_code) { case EXCEPTION_INT_DIVIDE_BY_ZERO: diff --git a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp index 3dbb8adddd6..98b17aaacfc 100644 --- a/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp +++ b/src/hotspot/os_cpu/aix_ppc/os_aix_ppc.cpp @@ -229,16 +229,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, CodeBlob *cb = nullptr; int stop_type = -1; - // Handle signal from NativeJump::patch_verified_entry(). - if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_not_entrant()) { - if (TraceTraps) { - tty->print_cr("trap: not_entrant"); - } - stub = SharedRuntime::get_handle_wrong_method_stub(); - goto run_stub; - } - - else if ((sig == (USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV)) && + if ((sig == (USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV)) && ((NativeInstruction*)pc)->is_safepoint_poll() && CodeCache::contains((void*) pc) && ((cb = CodeCache::find_blob(pc)) != nullptr) && diff --git a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp index ad32ee150e8..b7556ca69da 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/os_bsd_aarch64.cpp @@ -271,14 +271,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // Java thread running in Java code => find exception handler if any // a fault inside compiled code, the interpreter, or a stub - // Handle signal from NativeJump::patch_verified_entry(). - if ((sig == SIGILL) - && nativeInstruction_at(pc)->is_sigill_not_entrant()) { - if (TraceTraps) { - tty->print_cr("trap: not_entrant"); - } - stub = SharedRuntime::get_handle_wrong_method_stub(); - } else if ((sig == SIGSEGV || sig == SIGBUS) && SafepointMechanism::is_poll_address((address)info->si_addr)) { + if ((sig == SIGSEGV || sig == SIGBUS) && SafepointMechanism::is_poll_address((address)info->si_addr)) { stub = SharedRuntime::get_poll_stub(pc); #if defined(__APPLE__) // 32-bit Darwin reports a SIGBUS for nearly all memory access exceptions. diff --git a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp index 6900283418d..e565f353382 100644 --- a/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/os_linux_aarch64.cpp @@ -232,14 +232,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // Java thread running in Java code => find exception handler if any // a fault inside compiled code, the interpreter, or a stub - // Handle signal from NativeJump::patch_verified_entry(). - if ((sig == SIGILL || sig == SIGTRAP) - && nativeInstruction_at(pc)->is_sigill_not_entrant()) { - if (TraceTraps) { - tty->print_cr("trap: not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL"); - } - stub = SharedRuntime::get_handle_wrong_method_stub(); - } else if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) { + if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) { stub = SharedRuntime::get_poll_stub(pc); } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) { // BugId 4454115: A read from a MappedByteBuffer can fault diff --git a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp index 6c245f8f1a6..28b47877264 100644 --- a/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp +++ b/src/hotspot/os_cpu/linux_arm/os_linux_arm.cpp @@ -359,11 +359,6 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, stub = SharedRuntime::continuation_for_implicit_exception( thread, pc, SharedRuntime::IMPLICIT_NULL); } - } else if (sig == SIGILL && - *(int*)pc == - NativeInstruction::not_entrant_illegal_instruction) { - // Not entrant - stub = SharedRuntime::get_handle_wrong_method_stub(); } } else if ((thread->thread_state() == _thread_in_vm || thread->thread_state() == _thread_in_native) && diff --git a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp index 5fe37be0d20..55618947143 100644 --- a/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp +++ b/src/hotspot/os_cpu/linux_ppc/os_linux_ppc.cpp @@ -258,15 +258,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, CodeBlob *cb = nullptr; int stop_type = -1; - // Handle signal from NativeJump::patch_verified_entry(). - if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_not_entrant()) { - if (TraceTraps) { - tty->print_cr("trap: not_entrant"); - } - stub = SharedRuntime::get_handle_wrong_method_stub(); - } - - else if ((sig == (USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV)) && + if ((sig == (USE_POLL_BIT_ONLY ? SIGTRAP : SIGSEGV)) && // A linux-ppc64 kernel before 2.6.6 doesn't set si_addr on some segfaults // in 64bit mode (cf. http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.6), // especially when we try to read from the safepoint polling page. So the check diff --git a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp index 8366a7249fa..7a5929b0f41 100644 --- a/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp +++ b/src/hotspot/os_cpu/linux_riscv/os_linux_riscv.cpp @@ -223,14 +223,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // Java thread running in Java code => find exception handler if any // a fault inside compiled code, the interpreter, or a stub - // Handle signal from NativeJump::patch_verified_entry(). - if ((sig == SIGILL || sig == SIGTRAP) - && nativeInstruction_at(pc)->is_sigill_not_entrant()) { - if (TraceTraps) { - tty->print_cr("trap: not_entrant (%s)", (sig == SIGTRAP) ? "SIGTRAP" : "SIGILL"); - } - stub = SharedRuntime::get_handle_wrong_method_stub(); - } else if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) { + if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) { stub = SharedRuntime::get_poll_stub(pc); } else if (sig == SIGBUS /* && info->si_code == BUS_OBJERR */) { // BugId 4454115: A read from a MappedByteBuffer can fault diff --git a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp index 7e4d72fc066..4e074512e34 100644 --- a/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp +++ b/src/hotspot/os_cpu/linux_s390/os_linux_s390.cpp @@ -257,15 +257,7 @@ bool PosixSignals::pd_hotspot_signal_handler(int sig, siginfo_t* info, // Java thread running in Java code => find exception handler if any // a fault inside compiled code, the interpreter, or a stub - // Handle signal from NativeJump::patch_verified_entry(). - if (sig == SIGILL && nativeInstruction_at(pc)->is_sigill_not_entrant()) { - if (TraceTraps) { - tty->print_cr("trap: not_entrant (SIGILL)"); - } - stub = SharedRuntime::get_handle_wrong_method_stub(); - } - - else if (sig == SIGSEGV && + if (sig == SIGSEGV && SafepointMechanism::is_poll_address((address)info->si_addr)) { if (TraceTraps) { tty->print_cr("trap: safepoint_poll at " INTPTR_FORMAT " (SIGSEGV)", p2i(pc)); diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 8e1f93e7288..cfd31b8104a 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -28,7 +28,6 @@ #include "code/dependencies.hpp" #include "code/nativeInst.hpp" #include "code/nmethod.inline.hpp" -#include "code/relocInfo.hpp" #include "code/scopeDesc.hpp" #include "compiler/abstractCompiler.hpp" #include "compiler/compilationLog.hpp" @@ -692,13 +691,6 @@ address nmethod::oops_reloc_begin() const { } address low_boundary = verified_entry_point(); - if (!is_in_use()) { - low_boundary += NativeJump::instruction_size; - // %%% Note: On SPARC we patch only a 4-byte trap, not a full NativeJump. - // This means that the low_boundary is going to be a little too high. - // This shouldn't matter, since oops of non-entrant methods are never used. - // In fact, why are we bothering to look at oops in a non-entrant method?? - } return low_boundary; } @@ -1653,10 +1645,6 @@ void nmethod::maybe_print_nmethod(const DirectiveSet* directive) { } void nmethod::print_nmethod(bool printmethod) { - // Enter a critical section to prevent a race with deopts that patch code and updates the relocation info. - // Unfortunately, we have to lock the NMethodState_lock before the tty lock due to the deadlock rules and - // cannot lock in a more finely grained manner. - ConditionalMutexLocker ml(NMethodState_lock, !NMethodState_lock->owned_by_self(), Mutex::_no_safepoint_check_flag); ttyLocker ttyl; // keep the following output all in one block if (xtty != nullptr) { xtty->begin_head("print_nmethod"); @@ -2040,19 +2028,7 @@ bool nmethod::make_not_entrant(InvalidationReason invalidation_reason) { } else { // The caller can be calling the method statically or through an inline // cache call. - NativeJump::patch_verified_entry(entry_point(), verified_entry_point(), - SharedRuntime::get_handle_wrong_method_stub()); - - // Update the relocation info for the patched entry. - // First, get the old relocation info... - RelocIterator iter(this, verified_entry_point(), verified_entry_point() + 8); - if (iter.next() && iter.addr() == verified_entry_point()) { - Relocation* old_reloc = iter.reloc(); - // ...then reset the iterator to update it. - RelocIterator iter(this, verified_entry_point(), verified_entry_point() + 8); - relocInfo::change_reloc_info_for_address(&iter, verified_entry_point(), old_reloc->type(), - relocInfo::relocType::runtime_call_type); - } + BarrierSet::barrier_set()->barrier_set_nmethod()->make_not_entrant(this); } if (update_recompile_counts()) { @@ -2944,9 +2920,6 @@ void nmethod::verify() { if (is_not_entrant()) return; - // Make sure all the entry points are correctly aligned for patching. - NativeJump::check_verified_entry_alignment(entry_point(), verified_entry_point()); - // assert(oopDesc::is_oop(method()), "must be valid"); ResourceMark rm; diff --git a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp index 41eb0a24b62..522000e0a99 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.cpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.cpp @@ -72,11 +72,25 @@ bool BarrierSetNMethod::supports_entry_barrier(nmethod* nm) { } void BarrierSetNMethod::disarm(nmethod* nm) { - set_guard_value(nm, disarmed_guard_value()); + guard_with(nm, disarmed_guard_value()); +} + +void BarrierSetNMethod::guard_with(nmethod* nm, int value) { + assert((value & not_entrant) == 0, "not_entrant bit is reserved"); + // Enter critical section. Does not block for safepoint. + ConditionalMutexLocker ml(NMethodEntryBarrier_lock, !NMethodEntryBarrier_lock->owned_by_self(), Mutex::_no_safepoint_check_flag); + // Do not undo sticky bit + if (is_not_entrant(nm)) { + value |= not_entrant; + } + if (guard_value(nm) != value) { + // Patch the code only if needed. + set_guard_value(nm, value); + } } bool BarrierSetNMethod::is_armed(nmethod* nm) { - return guard_value(nm) != disarmed_guard_value(); + return (guard_value(nm) & ~not_entrant) != disarmed_guard_value(); } bool BarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { @@ -152,7 +166,7 @@ void BarrierSetNMethod::arm_all_nmethods() { // seriously wrong. ++_current_phase; if (_current_phase == INT_MAX) { - _current_phase = 1; + _current_phase = initial; } BarrierSetNMethodArmClosure cl(_current_phase); Threads::threads_do(&cl); @@ -178,23 +192,25 @@ int BarrierSetNMethod::nmethod_stub_entry_barrier(address* return_address_ptr) { BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); // Called upon first entry after being armed - bool may_enter = bs_nm->nmethod_entry_barrier(nm); + bool may_enter = !bs_nm->is_not_entrant(nm) && bs_nm->nmethod_entry_barrier(nm); assert(!nm->is_osr_method() || may_enter, "OSR nmethods should always be entrant after migration"); - // In case a concurrent thread disarmed the nmethod, we need to ensure the new instructions - // are made visible, by using a cross modify fence. Note that this is synchronous cross modifying - // code, where the existence of new instructions is communicated via data (the guard value). - // This cross modify fence is only needed when the nmethod entry barrier modifies the - // instructions. Not all platforms currently do that, so if this check becomes expensive, - // it can be made conditional on the nmethod_patching_type. - OrderAccess::cross_modify_fence(); - - // Diagnostic option to force deoptimization 1 in 10 times. It is otherwise - // a very rare event. - if (DeoptimizeNMethodBarriersALot && !nm->is_osr_method()) { - static volatile uint32_t counter=0; - if (Atomic::add(&counter, 1u) % 10 == 0) { - may_enter = false; + if (may_enter) { + // In case a concurrent thread disarmed the nmethod, we need to ensure the new instructions + // are made visible, by using a cross modify fence. Note that this is synchronous cross modifying + // code, where the existence of new instructions is communicated via data (the guard value). + // This cross modify fence is only needed when the nmethod entry barrier modifies the + // instructions. Not all platforms currently do that, so if this check becomes expensive, + // it can be made conditional on the nmethod_patching_type. + OrderAccess::cross_modify_fence(); + + // Diagnostic option to force deoptimization 1 in 10 times. It is otherwise + // a very rare event. + if (DeoptimizeNMethodBarriersALot && !nm->is_osr_method()) { + static volatile uint32_t counter=0; + if (Atomic::add(&counter, 1u) % 10 == 0) { + may_enter = false; + } } } @@ -220,3 +236,22 @@ oop BarrierSetNMethod::oop_load_no_keepalive(const nmethod* nm, int index) { oop BarrierSetNMethod::oop_load_phantom(const nmethod* nm, int index) { return NativeAccess::oop_load(nm->oop_addr_at(index)); } + +// Make the nmethod permanently not-entrant, so that nmethod_stub_entry_barrier() will call +// deoptimize() to redirect the caller to SharedRuntime::get_handle_wrong_method_stub(). +// A sticky armed bit is set and other bits are preserved. As a result, a call to +// nmethod_stub_entry_barrier() may appear to be spurious, because is_armed() still returns +// false and nmethod_entry_barrier() is not called. +void BarrierSetNMethod::make_not_entrant(nmethod* nm) { + // Enter critical section. Does not block for safepoint. + ConditionalMutexLocker ml(NMethodEntryBarrier_lock, !NMethodEntryBarrier_lock->owned_by_self(), Mutex::_no_safepoint_check_flag); + int value = guard_value(nm) | not_entrant; + if (guard_value(nm) != value) { + // Patch the code only if needed. + set_guard_value(nm, value); + } +} + +bool BarrierSetNMethod::is_not_entrant(nmethod* nm) { + return (guard_value(nm) & not_entrant) != 0; +} diff --git a/src/hotspot/share/gc/shared/barrierSetNMethod.hpp b/src/hotspot/share/gc/shared/barrierSetNMethod.hpp index 756dc43b3f1..b905e8869b5 100644 --- a/src/hotspot/share/gc/shared/barrierSetNMethod.hpp +++ b/src/hotspot/share/gc/shared/barrierSetNMethod.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,10 +36,20 @@ class nmethod; class BarrierSetNMethod: public CHeapObj { private: int _current_phase; + enum { + not_entrant = 1 << 31, // armed sticky bit, see make_not_entrant + armed = 0, + initial = 1, + }; + void deoptimize(nmethod* nm, address* return_addr_ptr); +protected: + virtual int guard_value(nmethod* nm); + void set_guard_value(nmethod* nm, int value); + public: - BarrierSetNMethod() : _current_phase(1) {} + BarrierSetNMethod() : _current_phase(initial) {} bool supports_entry_barrier(nmethod* nm); virtual bool nmethod_entry_barrier(nmethod* nm); @@ -50,13 +60,15 @@ class BarrierSetNMethod: public CHeapObj { static int nmethod_stub_entry_barrier(address* return_address_ptr); bool nmethod_osr_entry_barrier(nmethod* nm); - bool is_armed(nmethod* nm); + virtual bool is_armed(nmethod* nm); + void arm(nmethod* nm) { guard_with(nm, armed); } void disarm(nmethod* nm); + virtual void make_not_entrant(nmethod* nm); + virtual bool is_not_entrant(nmethod* nm); - int guard_value(nmethod* nm); - void set_guard_value(nmethod* nm, int value); + virtual void guard_with(nmethod* nm, int value); - void arm_all_nmethods(); + virtual void arm_all_nmethods(); virtual oop oop_load_no_keepalive(const nmethod* nm, int index); virtual oop oop_load_phantom(const nmethod* nm, int index); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp index 49d2df0cc93..0d9077be226 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCodeRoots.cpp @@ -150,7 +150,7 @@ class ShenandoahNMethodUnlinkClosure : public NMethodClosure { ShenandoahNMethod::heal_nmethod_metadata(nm_data); // Code cache unloading needs to know about on-stack nmethods. Arm the nmethods to get // mark_as_maybe_on_stack() callbacks when they are used again. - _bs->set_guard_value(nm, 0); + _bs->arm(nm); } } diff --git a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp index 0d6be2b789f..392d194a65b 100644 --- a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp @@ -105,3 +105,36 @@ oop ZBarrierSetNMethod::oop_load_no_keepalive(const nmethod* nm, int index) { oop ZBarrierSetNMethod::oop_load_phantom(const nmethod* nm, int index) { return ZNMethod::oop_load_phantom(nm, index); } + +void ZBarrierSetNMethod::guard_with(nmethod* nm, int value) { + assert((value & not_entrant) == 0, "not_entrant bit is reserved"); + ZLocker locker(ZNMethod::lock_for_nmethod(nm)); + // Preserve the sticky bit + if (is_not_entrant(nm)) { + value |= not_entrant; + } + if (guard_value(nm) != value) { + // Patch the code only if needed. + set_guard_value(nm, value); + } +} + +bool ZBarrierSetNMethod::is_armed(nmethod* nm) { + int value = guard_value(nm) & ~not_entrant; + return value != disarmed_guard_value(); +} + +void ZBarrierSetNMethod::make_not_entrant(nmethod* nm) { + ZLocker locker(ZNMethod::lock_for_nmethod(nm)); + int value = guard_value(nm) | not_entrant; // permanent sticky value + set_guard_value(nm, value); +} + +bool ZBarrierSetNMethod::is_not_entrant(nmethod* nm) { + return (guard_value(nm) & not_entrant) != 0; +} + +uintptr_t ZBarrierSetNMethod::color(nmethod* nm) { + // color is stored at low order bits of int; conversion to uintptr_t is fine + return uintptr_t(guard_value(nm) & ~not_entrant); +} diff --git a/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp b/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp index 780d3772123..e0b7ba6c773 100644 --- a/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.hpp @@ -30,15 +30,27 @@ class nmethod; class ZBarrierSetNMethod : public BarrierSetNMethod { + enum : int { + not_entrant = 1 << 31, // armed sticky bit, see make_not_entrant + }; + protected: virtual bool nmethod_entry_barrier(nmethod* nm); public: + uintptr_t color(nmethod* nm); + virtual ByteSize thread_disarmed_guard_value_offset() const; virtual int* disarmed_guard_value_address() const; virtual oop oop_load_no_keepalive(const nmethod* nm, int index); virtual oop oop_load_phantom(const nmethod* nm, int index); + + virtual void make_not_entrant(nmethod* nm); + virtual bool is_not_entrant(nmethod* nm); + virtual void guard_with(nmethod* nm, int value); + virtual bool is_armed(nmethod* nm); + virtual void arm_all_nmethods() { ShouldNotCallThis(); } }; #endif // SHARE_GC_Z_ZBARRIERSETNMETHOD_HPP diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index de66bbed8df..d1646da7604 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -773,7 +773,7 @@ class ZMarkYoungNMethodClosure : public NMethodClosure { ZNMethod::nmethod_patch_barriers(nm); } - _bs_nm->set_guard_value(nm, (int)untype(new_disarm_value_ptr)); + _bs_nm->guard_with(nm, (int)untype(new_disarm_value_ptr)); if (complete_disarm) { log_trace(gc, nmethod)("nmethod: " PTR_FORMAT " visited by young (complete) [" PTR_FORMAT " -> " PTR_FORMAT "]", p2i(nm), prev_color, untype(new_disarm_value_ptr)); diff --git a/src/hotspot/share/gc/z/zNMethod.cpp b/src/hotspot/share/gc/z/zNMethod.cpp index bf592c20fa2..3f65d2eea97 100644 --- a/src/hotspot/share/gc/z/zNMethod.cpp +++ b/src/hotspot/share/gc/z/zNMethod.cpp @@ -241,7 +241,7 @@ void ZNMethod::disarm(nmethod* nm) { void ZNMethod::set_guard_value(nmethod* nm, int value) { BarrierSetNMethod* const bs = BarrierSet::barrier_set()->barrier_set_nmethod(); - bs->set_guard_value(nm, value); + bs->guard_with(nm, value); } void ZNMethod::nmethod_patch_barriers(nmethod* nm) { @@ -300,9 +300,8 @@ void ZNMethod::nmethods_do(bool secondary, NMethodClosure* cl) { } uintptr_t ZNMethod::color(nmethod* nm) { - BarrierSetNMethod* bs_nm = BarrierSet::barrier_set()->barrier_set_nmethod(); - // color is stored at low order bits of int; conversion to uintptr_t is fine - return (uintptr_t)bs_nm->guard_value(nm); + ZBarrierSetNMethod* bs_nm = static_cast(BarrierSet::barrier_set()->barrier_set_nmethod()); + return bs_nm->color(nm); } oop ZNMethod::oop_load_no_keepalive(const nmethod* nm, int index) { diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 36e0cfe1125..b90f8c23a6d 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -36,6 +36,7 @@ // Mutexes used in the VM (see comment in mutexLocker.hpp): Mutex* NMethodState_lock = nullptr; +Mutex* NMethodEntryBarrier_lock = nullptr; Monitor* SystemDictionary_lock = nullptr; Mutex* InvokeMethodTypeTable_lock = nullptr; Monitor* InvokeMethodIntrinsicTable_lock = nullptr; @@ -205,6 +206,8 @@ void assert_lock_strong(const Mutex* lock) { void mutex_init() { MUTEX_DEFN(tty_lock , PaddedMutex , tty); // allow to lock in VM + MUTEX_DEFN(NMethodEntryBarrier_lock , PaddedMutex , service-1); + MUTEX_DEFN(STS_lock , PaddedMonitor, nosafepoint); if (UseG1GC) { diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index 6baa93b2579..640747c3fe9 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -34,6 +34,7 @@ class Thread; // Mutexes used in the VM. extern Mutex* NMethodState_lock; // a lock used to guard a compiled method state +extern Mutex* NMethodEntryBarrier_lock; // protects nmethod entry barrier extern Monitor* SystemDictionary_lock; // a lock on the system dictionary extern Mutex* InvokeMethodTypeTable_lock; extern Monitor* InvokeMethodIntrinsicTable_lock; From 1ca008fd02496dc33e2707c102560cae1690fba5 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Thu, 26 Jun 2025 01:02:03 +0000 Subject: [PATCH 185/213] 8360255: runtime/jni/checked/TestLargeUTF8Length.java fails with -XX:-CompactStrings Reviewed-by: shade, kbarrett --- .../runtime/jni/checked/TestLargeUTF8Length.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java b/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java index 9186a7ea381..50f8385bb6d 100644 --- a/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java +++ b/test/hotspot/jtreg/runtime/jni/checked/TestLargeUTF8Length.java @@ -44,9 +44,14 @@ public class TestLargeUTF8Length { static native void checkUTF8Length(String s, long utf8Length); static void test() { - int length = Integer.MAX_VALUE/2 + 1; - char character = (char)0XD1; // N with tilde - long utf8Length = 2L * length; + // We want a string whose UTF-8 length is > Integer.MAX_VALUE, but + // whose "natural" length is < Integer.MAX_VALUE/2 so it can be + // created regardless of whether compact-strings are enabled or not. + // So we use a character that encodes as 3-bytes in UTF-8. + // U+08A0 : e0 a2 a0 : ARABIC LETTER BEH WITH SMALL V BELOW + char character = '\u08A0'; + int length = Integer.MAX_VALUE/2 - 1; + long utf8Length = 3L * length; char[] chrs = new char[length]; Arrays.fill(chrs, character); String s = new String(chrs); From 5039b42de170769797312969185ee9d67f34cf24 Mon Sep 17 00:00:00 2001 From: Anton Artemov Date: Thu, 26 Jun 2025 07:41:22 +0000 Subject: [PATCH 186/213] 8359437: Make users and test suite not able to set LockingMode flag 8358542: Remove RTM test VMProps Co-authored-by: Fredrik Bredberg Reviewed-by: coleenp, lmesnik, fbredberg, alanb, dholmes --- src/hotspot/share/prims/whitebox.cpp | 1 + src/hotspot/share/runtime/arguments.cpp | 12 - src/hotspot/share/runtime/globals.hpp | 7 - .../share/utilities/globalDefinitions.cpp | 2 + .../share/utilities/globalDefinitions.hpp | 2 + .../sun/jvm/hotspot/runtime/LockingMode.java | 60 ---- .../sun/jvm/hotspot/runtime/Threads.java | 33 +- test/hotspot/jtreg/ProblemList-StaticJdk.txt | 1 - test/hotspot/jtreg/TEST.groups | 1 - .../locks/TestSynchronizeWithEmptyBlock.java | 5 +- test/hotspot/jtreg/gtest/LockStackGtests.java | 32 -- .../runtime/Monitor/ConcurrentDeflation.java | 14 +- ...tressWrapper_TestRecursiveLocking_36M.java | 90 ------ .../runtime/Monitor/TestRecursiveLocking.java | 195 +++-------- .../lockStack/TestLockStackCapacity.java | 12 +- .../locking/TestRecursiveMonitorChurn.java | 5 +- .../vthread/JNIMonitor/JNIMonitor.java | 303 ------------------ .../StopThreadTest/StopThreadTest.java | 9 +- test/jdk/com/sun/jdi/EATests.java | 72 +---- .../Thread/virtual/CarrierThreadInfo.java | 26 +- .../java/lang/Thread/virtual/LockingMode.java | 39 --- .../lang/Thread/virtual/MiscMonitorTests.java | 14 +- .../lang/Thread/virtual/MonitorEnterExit.java | 73 +---- .../Thread/virtual/MonitorWaitNotify.java | 74 +---- .../jdk/java/lang/Thread/virtual/Parking.java | 9 +- .../virtual/RetryMonitorEnterWhenPinned.java | 1 - .../java/lang/Thread/virtual/ThreadAPI.java | 4 - .../stress/LotsOfContendedMonitorEnter.java | 10 +- .../stress/LotsOfUncontendedMonitorEnter.java | 14 +- .../stress/Skynet100kWithMonitors.java | 6 +- .../ConcurrentHashMap/MapLoops.java | 9 - .../jdk/internal/vm/Continuation/Basic.java | 43 +-- .../jdk/internal/vm/Continuation/Fuzz.java | 10 +- test/jtreg-ext/requires/VMProps.java | 52 --- 34 files changed, 110 insertions(+), 1130 deletions(-) delete mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/LockingMode.java delete mode 100644 test/hotspot/jtreg/gtest/LockStackGtests.java delete mode 100644 test/hotspot/jtreg/runtime/vthread/JNIMonitor/JNIMonitor.java delete mode 100644 test/jdk/java/lang/Thread/virtual/LockingMode.java diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index d025a8937c8..60ebba36f92 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -85,6 +85,7 @@ #include "runtime/javaCalls.hpp" #include "runtime/javaThread.inline.hpp" #include "runtime/jniHandles.inline.hpp" +#include "runtime/lightweightSynchronizer.hpp" #include "runtime/lockStack.hpp" #include "runtime/os.hpp" #include "runtime/stackFrameStream.inline.hpp" diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 0d39fed52db..07a26916256 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -1836,15 +1836,6 @@ bool Arguments::check_vm_args_consistency() { } #endif -#ifndef _LP64 - if (LockingMode == LM_LEGACY) { - FLAG_SET_CMDLINE(LockingMode, LM_LIGHTWEIGHT); - // Self-forwarding in bit 3 of the mark-word conflicts - // with 4-byte-aligned stack-locks. - warning("Legacy locking not supported on this platform"); - } -#endif - if (UseObjectMonitorTable && LockingMode != LM_LIGHTWEIGHT) { // ObjectMonitorTable requires lightweight locking. FLAG_SET_CMDLINE(UseObjectMonitorTable, false); @@ -3770,9 +3761,6 @@ void Arguments::set_compact_headers_flags() { FLAG_SET_DEFAULT(UseObjectMonitorTable, true); } } - if (UseCompactObjectHeaders && LockingMode != LM_LIGHTWEIGHT) { - FLAG_SET_DEFAULT(LockingMode, LM_LIGHTWEIGHT); - } if (UseCompactObjectHeaders && !UseCompressedClassPointers) { FLAG_SET_DEFAULT(UseCompressedClassPointers, true); } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 91dadd05180..b61c3724dba 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1957,13 +1957,6 @@ const int ObjectAlignmentInBytes = 8; "Mark all threads after a safepoint, and clear on a modify " \ "fence. Add cleanliness checks.") \ \ - product(int, LockingMode, LM_LIGHTWEIGHT, \ - "(Deprecated) Select locking mode: " \ - "0: (Deprecated) monitors only (LM_MONITOR), " \ - "1: (Deprecated) monitors & legacy stack-locking (LM_LEGACY), " \ - "2: monitors & new lightweight locking (LM_LIGHTWEIGHT, default)") \ - range(0, 2) \ - \ product(bool, UseObjectMonitorTable, false, DIAGNOSTIC, \ "With Lightweight Locking mode, use a table to record inflated " \ "monitors rather than the first word of the object.") \ diff --git a/src/hotspot/share/utilities/globalDefinitions.cpp b/src/hotspot/share/utilities/globalDefinitions.cpp index 8a111a12607..84a0730212f 100644 --- a/src/hotspot/share/utilities/globalDefinitions.cpp +++ b/src/hotspot/share/utilities/globalDefinitions.cpp @@ -56,6 +56,8 @@ int LogMinObjAlignmentInBytes = -1; // Oop encoding heap max uint64_t OopEncodingHeapMax = 0; +const int LockingMode = LM_LIGHTWEIGHT; + // Something to help porters sleep at night #ifdef ASSERT diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 4ec61babec3..46daa867644 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -1009,6 +1009,8 @@ enum LockingMode { LM_LIGHTWEIGHT = 2 }; +extern const int LockingMode; + //---------------------------------------------------------------------------------------------------- // Special constants for debugging diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/LockingMode.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/LockingMode.java deleted file mode 100644 index 2046fd075ad..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/LockingMode.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package sun.jvm.hotspot.runtime; - -import sun.jvm.hotspot.types.TypeDataBase; - - -/** Encapsulates the LockingMode enum in globalDefinitions.hpp in - the VM. */ - -public class LockingMode { - private static int monitor; - private static int legacy; - private static int lightweight; - - static { - VM.registerVMInitializedObserver( - (o, d) -> initialize(VM.getVM().getTypeDataBase())); - } - - private static synchronized void initialize(TypeDataBase db) { - monitor = db.lookupIntConstant("LM_MONITOR").intValue(); - legacy = db.lookupIntConstant("LM_LEGACY").intValue(); - lightweight = db.lookupIntConstant("LM_LIGHTWEIGHT").intValue(); - } - - public static int getMonitor() { - return monitor; - } - - public static int getLegacy() { - return legacy; - } - - public static int getLightweight() { - return lightweight; - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java index dfc49d1a81f..1230bea184c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java @@ -222,29 +222,18 @@ private JavaThread owningThreadFromMonitor(Address o) { public JavaThread owningThreadFromMonitor(ObjectMonitor monitor) { if (monitor.isOwnedAnonymous()) { - if (VM.getVM().getCommandLineFlag("LockingMode").getInt() == LockingMode.getLightweight()) { - OopHandle object = monitor.object(); - for (int i = 0; i < getNumberOfThreads(); i++) { - JavaThread thread = getJavaThreadAt(i); - if (thread.isLockOwned(object)) { - return thread; - } - } - // We should have found the owner, however, as the VM could be in any state, including the middle - // of performing GC, it is not always possible to do so. Just return null if we can't locate it. - System.out.println("Warning: We failed to find a thread that owns an anonymous lock. This is likely"); - System.out.println("due to the JVM currently running a GC. Locking information may not be accurate."); - return null; - } else { - assert(VM.getVM().getCommandLineFlag("LockingMode").getInt() == LockingMode.getLegacy()); - Address o = (Address)monitor.stackLocker(); - for (int i = 0; i < getNumberOfThreads(); i++) { - JavaThread thread = getJavaThreadAt(i); - if (thread.isLockOwned(o)) - return thread; - } - return null; + OopHandle object = monitor.object(); + for (int i = 0; i < getNumberOfThreads(); i++) { + JavaThread thread = getJavaThreadAt(i); + if (thread.isLockOwned(object)) { + return thread; + } } + // We should have found the owner, however, as the VM could be in any state, including the middle + // of performing GC, it is not always possible to do so. Just return null if we can't locate it. + System.out.println("Warning: We failed to find a thread that owns an anonymous lock. This is likely"); + System.out.println("due to the JVM currently running a GC. Locking information may not be accurate."); + return null; } else { return owningThreadFromMonitor(monitor.owner()); } diff --git a/test/hotspot/jtreg/ProblemList-StaticJdk.txt b/test/hotspot/jtreg/ProblemList-StaticJdk.txt index cb727e470f3..1681fb74634 100644 --- a/test/hotspot/jtreg/ProblemList-StaticJdk.txt +++ b/test/hotspot/jtreg/ProblemList-StaticJdk.txt @@ -37,7 +37,6 @@ serviceability/sa/ClhsdbPstack.java#core 8346719 generic-all gtest/GTestWrapper.java 8356201 generic-all gtest/LargePageGtests.java#use-large-pages 8356201 generic-all gtest/LargePageGtests.java#use-large-pages-1G 8356201 generic-all -gtest/LockStackGtests.java 8356201 generic-all gtest/MetaspaceGtests.java#no-ccs 8356201 generic-all gtest/NMTGtests.java#nmt-detail 8356201 generic-all gtest/NMTGtests.java#nmt-off 8356201 generic-all diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 2fa0862a186..c6609e248d3 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -142,7 +142,6 @@ tier1_common = \ sources \ sanity/BasicVMTest.java \ gtest/GTestWrapper.java \ - gtest/LockStackGtests.java \ gtest/MetaspaceGtests.java \ gtest/LargePageGtests.java \ gtest/NMTGtests.java \ diff --git a/test/hotspot/jtreg/compiler/locks/TestSynchronizeWithEmptyBlock.java b/test/hotspot/jtreg/compiler/locks/TestSynchronizeWithEmptyBlock.java index 4165e6285b6..1f861f301e3 100644 --- a/test/hotspot/jtreg/compiler/locks/TestSynchronizeWithEmptyBlock.java +++ b/test/hotspot/jtreg/compiler/locks/TestSynchronizeWithEmptyBlock.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,6 @@ * @bug 8337660 * @summary Test that C2 does not remove blocks with BoxLock nodes that are * otherwise empty. - * @run main/othervm -Xbatch -XX:LockingMode=1 - * -XX:CompileOnly=compiler.locks.TestSynchronizeWithEmptyBlock::* - * compiler.locks.TestSynchronizeWithEmptyBlock * @run main/othervm -Xbatch * -XX:CompileOnly=compiler.locks.TestSynchronizeWithEmptyBlock::* * compiler.locks.TestSynchronizeWithEmptyBlock diff --git a/test/hotspot/jtreg/gtest/LockStackGtests.java b/test/hotspot/jtreg/gtest/LockStackGtests.java deleted file mode 100644 index e426b2c56f3..00000000000 --- a/test/hotspot/jtreg/gtest/LockStackGtests.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -/* @test - * @summary Run LockStack gtests with LockingMode=2 - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @requires vm.flagless - * @run main/native GTestWrapper --gtest_filter=LockStackTest* -XX:LockingMode=2 - */ diff --git a/test/hotspot/jtreg/runtime/Monitor/ConcurrentDeflation.java b/test/hotspot/jtreg/runtime/Monitor/ConcurrentDeflation.java index 9ceec3b9d8d..88dafed4a41 100644 --- a/test/hotspot/jtreg/runtime/Monitor/ConcurrentDeflation.java +++ b/test/hotspot/jtreg/runtime/Monitor/ConcurrentDeflation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.Platform; import jdk.test.lib.process.ProcessTools; +import jdk.test.whitebox.WhiteBox; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; @@ -34,10 +35,13 @@ * @bug 8318757 * @summary Test concurrent monitor deflation by MonitorDeflationThread and thread dumping * @library /test/lib - * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedAsyncDeflationInterval=2000 -XX:LockingMode=0 ConcurrentDeflation + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:GuaranteedAsyncDeflationInterval=2000 -XX:+WhiteBoxAPI ConcurrentDeflation */ public class ConcurrentDeflation { + static final WhiteBox WB = WhiteBox.getWhiteBox(); public static final long TOTAL_RUN_TIME_NS = 10_000_000_000L; public static Object[] monitors = new Object[1000]; public static int monitorCount; @@ -73,6 +77,12 @@ static private void createMonitors() { index = index++ % 1000; monitors[index] = new Object(); synchronized (monitors[index]) { + try { + // Force inflation + monitors[index].wait(1); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } monitorCount++; } } diff --git a/test/hotspot/jtreg/runtime/Monitor/StressWrapper_TestRecursiveLocking_36M.java b/test/hotspot/jtreg/runtime/Monitor/StressWrapper_TestRecursiveLocking_36M.java index b12f0f007f8..0eeacabb82f 100644 --- a/test/hotspot/jtreg/runtime/Monitor/StressWrapper_TestRecursiveLocking_36M.java +++ b/test/hotspot/jtreg/runtime/Monitor/StressWrapper_TestRecursiveLocking_36M.java @@ -33,21 +33,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -Xint - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 1 */ @@ -63,21 +48,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -Xint - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 2 */ @@ -94,21 +64,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 1 */ @@ -125,21 +80,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 2 */ @@ -156,21 +96,6 @@ * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-EliminateNestedLocks - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-EliminateNestedLocks - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 1 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-EliminateNestedLocks - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 120 1 */ @@ -182,25 +107,10 @@ * @summary Tests recursive locking in C2 in alternate A and B mode. * @library /testlibrary /test/lib * @build jdk.test.whitebox.WhiteBox - * * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=0 - * -XX:-EliminateNestedLocks - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 - * - * @run main/othervm/timeout=240 -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=1 - * -XX:-EliminateNestedLocks - * -Xms256m -Xmx256m - * TestRecursiveLocking 120 2 * * @run main/othervm/timeout=240 -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=2 * -XX:-EliminateNestedLocks * -Xms256m -Xmx256m * TestRecursiveLocking 120 2 diff --git a/test/hotspot/jtreg/runtime/Monitor/TestRecursiveLocking.java b/test/hotspot/jtreg/runtime/Monitor/TestRecursiveLocking.java index eae845c48b1..bea7a41ae2b 100644 --- a/test/hotspot/jtreg/runtime/Monitor/TestRecursiveLocking.java +++ b/test/hotspot/jtreg/runtime/Monitor/TestRecursiveLocking.java @@ -33,21 +33,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -Xint - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 1 */ @@ -63,21 +48,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -Xint - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xint - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 2 */ @@ -94,21 +64,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 1 */ @@ -125,21 +80,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:TieredStopAtLevel=1 - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 2 */ @@ -156,21 +96,6 @@ * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-EliminateNestedLocks - * -XX:LockingMode=0 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-EliminateNestedLocks - * -XX:LockingMode=1 - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 1 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-EliminateNestedLocks - * -XX:LockingMode=2 * -Xms256m -Xmx256m * TestRecursiveLocking 5 1 */ @@ -182,25 +107,10 @@ * @summary Tests recursive locking in C2 in alternate A and B mode. * @library /testlibrary /test/lib * @build jdk.test.whitebox.WhiteBox - * * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=0 - * -XX:-EliminateNestedLocks - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 - * - * @run main/othervm -Xbootclasspath/a:. - * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=1 - * -XX:-EliminateNestedLocks - * -Xms256m -Xmx256m - * TestRecursiveLocking 5 2 * * @run main/othervm -Xbootclasspath/a:. * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:LockingMode=2 * -XX:-EliminateNestedLocks * -Xms256m -Xmx256m * TestRecursiveLocking 5 2 @@ -212,11 +122,7 @@ public class TestRecursiveLocking { static final WhiteBox WB = WhiteBox.getWhiteBox(); - static final int flagLockingMode = WB.getIntVMFlag("LockingMode").intValue(); static final int constLockStackCapacity = WB.getLockStackCapacity(); - static final int LM_MONITOR = 0; - static final int LM_LEGACY = 1; - static final int LM_LIGHTWEIGHT = 2; static final int def_mode = 2; static final int def_n_secs = 30; static final SyncThread syncThread = new SyncThread(); @@ -229,44 +135,32 @@ static class SynchronizedObject { synchronized void runInner(int depth, SynchronizedObject outer) { counter++; - // Legacy mode has no lock stack, i.e., there is no limit - // on recursion, so for legacy mode we can't say that - // "outer" must be inflated here, which we can say for all - // the other locking modes. - if (flagLockingMode != LM_LEGACY) { - outer.assertInflated(); - } + // There is limit on recursion, so "outer" must be + // inflated here. + outer.assertInflated(); // We haven't reached the stack lock capacity (recursion // level), so we shouldn't be inflated here. Except for // monitor mode, which is always inflated. - if (flagLockingMode != LM_MONITOR) { - assertNotInflated(); - } + assertNotInflated(); if (depth == 1) { return; } else { runInner(depth - 1, outer); } - if (flagLockingMode != LM_MONITOR) { - assertNotInflated(); - } + assertNotInflated(); } synchronized void runOuter(int depth, SynchronizedObject inner) { counter++; - if (flagLockingMode != LM_MONITOR) { - assertNotInflated(); - } + assertNotInflated(); if (depth == 1) { inner.runInner(constLockStackCapacity, this); } else { runOuter(depth - 1, inner); } - if (flagLockingMode != LM_LEGACY) { - assertInflated(); - } + assertInflated(); } // This test nests x recursive locks of INNER, in x recursive @@ -283,18 +177,11 @@ public void runOuterInnerTest() { synchronized (OUTER) { OUTER.counter++; - if (flagLockingMode != LM_MONITOR) { - OUTER.assertNotInflated(); - } + OUTER.assertNotInflated(); INNER.assertNotInflated(); OUTER.runOuter(constLockStackCapacity - 1, INNER); - - if (flagLockingMode != LM_LEGACY) { - OUTER.assertInflated(); - } - if (flagLockingMode != LM_MONITOR) { - INNER.assertNotInflated(); - } + OUTER.assertInflated(); + INNER.assertNotInflated(); } // Verify that the nested monitors have been properly released: @@ -308,25 +195,23 @@ public void runOuterInnerTest() { synchronized void runA(int depth, SynchronizedObject B) { counter++; - if (flagLockingMode == LM_LIGHTWEIGHT) { - // First time we lock A, A is the only one on the lock - // stack. - if (counter == 1) { - assertNotInflated(); - } else { - // Second time we want to lock A, the lock stack - // looks like this [A, B]. Lightweight locking - // doesn't allow interleaving ([A, B, A]), instead - // it inflates A and removes it from the lock - // stack. Which leaves us with only [B] on the - // lock stack. After more recursions it will grow - // to [B, B ... B]. - assertInflated(); - } - } else if (flagLockingMode == LM_MONITOR) { + + // First time we lock A, A is the only one on the lock + // stack. + if (counter == 1) { + assertNotInflated(); + } else { + // Second time we want to lock A, the lock stack + // looks like this [A, B]. Lightweight locking + // doesn't allow interleaving ([A, B, A]), instead + // it inflates A and removes it from the lock + // stack. Which leaves us with only [B] on the + // lock stack. After more recursions it will grow + // to [B, B ... B]. assertInflated(); } + // Call runB() at the same depth as runA's depth: B.runB(depth, this); } @@ -334,16 +219,13 @@ synchronized void runA(int depth, SynchronizedObject B) { synchronized void runB(int depth, SynchronizedObject A) { counter++; - if (flagLockingMode != LM_MONITOR) { - // Legacy tolerates endless recursions. While testing - // lightweight we don't go deeper than the size of the - // lock stack, which in this test case will be filled - // with a number of B-elements. See comment in runA() - // above for more info. - assertNotInflated(); - } else { - assertInflated(); - } + + // Legacy tolerates endless recursions. While testing + // lightweight we don't go deeper than the size of the + // lock stack, which in this test case will be filled + // with a number of B-elements. See comment in runA() + // above for more info. + assertNotInflated(); if (depth == 1) { // Reached LockStackCapacity in depth so we're done. @@ -370,16 +252,12 @@ public void runAlternateABTest() { Asserts.assertEquals(A.counter, constLockStackCapacity); Asserts.assertEquals(B.counter, constLockStackCapacity); - if (flagLockingMode == LM_LEGACY) { - A.assertNotInflated(); - } - // Implied else: for LM_MONITOR or LM_LIGHTWEIGHT it can be - // either inflated or not because A is not locked anymore - // and subject to deflation. - if (flagLockingMode != LM_MONITOR) { - B.assertNotInflated(); - } + // Here A can be either inflated or not because A is not + // locked anymore and subject to deflation. + + B.assertNotInflated(); + } void assertNotInflated() { @@ -443,7 +321,6 @@ public static void main(String... argv) throws Exception { } } - System.out.println("INFO: LockingMode=" + flagLockingMode); System.out.println("INFO: LockStackCapacity=" + constLockStackCapacity); System.out.println("INFO: n_secs=" + n_secs); System.out.println("INFO: mode=" + mode); diff --git a/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java b/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java index 01ba1f4f12c..f3f1f9c91a6 100644 --- a/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java +++ b/test/hotspot/jtreg/runtime/lockStack/TestLockStackCapacity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ * @library /testlibrary /test/lib * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xint -XX:LockingMode=2 TestLockStackCapacity + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xint TestLockStackCapacity */ import jdk.test.lib.Asserts; @@ -39,8 +39,6 @@ public class TestLockStackCapacity { static final WhiteBox WB = WhiteBox.getWhiteBox(); - static final int LockingMode = WB.getIntVMFlag("LockingMode").intValue(); - static final int LM_LIGHTWEIGHT = 2; static class SynchronizedObject { static final SynchronizedObject OUTER = new SynchronizedObject(); @@ -95,12 +93,8 @@ void assertInflated() { } public static void main(String... args) throws Exception { - if (LockingMode != LM_LIGHTWEIGHT) { - throw new SkippedException("Test only valid for LM_LIGHTWEIGHT"); - } - if (!WB.supportsRecursiveLightweightLocking()) { - throw new SkippedException("Test only valid if LM_LIGHTWEIGHT supports recursion"); + throw new SkippedException("Test only valid if lightweight locking supports recursion"); } SynchronizedObject.runTest(); diff --git a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java index 806f32aad88..e92e947ecfa 100644 --- a/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java +++ b/test/hotspot/jtreg/runtime/locking/TestRecursiveMonitorChurn.java @@ -49,13 +49,12 @@ synchronized void doSomethingElse() { } static final WhiteBox WB = WhiteBox.getWhiteBox(); - static final int LM_MONITOR = 0; static final int COUNT = 100000; public static volatile Monitor monitor; public static void main(String[] args) { - if (WB.getIntVMFlag("LockingMode") == LM_MONITOR) { - throw new SkippedException("LM_MONITOR always inflates. Invalid test."); + if (WB.getBooleanVMFlag("VerifyHeavyMonitors")) { + throw new SkippedException("VerifyHeavyMonitors always inflates. Invalid test."); } final long pre_monitor_count = WB.getInUseMonitorCount(); System.out.println(" Precount = " + pre_monitor_count); diff --git a/test/hotspot/jtreg/runtime/vthread/JNIMonitor/JNIMonitor.java b/test/hotspot/jtreg/runtime/vthread/JNIMonitor/JNIMonitor.java deleted file mode 100644 index 56bb705a0b2..00000000000 --- a/test/hotspot/jtreg/runtime/vthread/JNIMonitor/JNIMonitor.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * 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 - * 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 jdk.test.lib.Asserts; -import jdk.test.lib.Utils; -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.ThreadFactory; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/* - * Tests that JNI monitors work correctly with virtual threads, - * There are multiple test scenarios that we check using unified logging output - * (both positive and negative tests). Each test case is handled by its own @-test - * definition so that we can run each sub-test independently. - * - * The original bug was only discovered because the ForkJoinPool worker thread terminated - * and trigerred an assertion failure. So we use a custom scheduler to give us control. - */ - -/** - * @test id=normal - * @bug 8327743 - * @summary Normal lock then unlock - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor Normal - */ - -/** - * @test id=multiNormal - * @bug 8327743 - * @summary Normal lock then unlock by multiple threads - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MultiNormal - */ - -/** - * @test id=missingUnlock - * @bug 8327743 - * @summary Don't do the unlock and exit normally - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MissingUnlock - */ - -/** - * @test id=multiMissingUnlock - * @bug 8327743 - * @summary Don't do the unlock and exit normally, by multiple threads - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MultiMissingUnlock - */ - -/** - * @test id=missingUnlockWithThrow - * @bug 8327743 - * @summary Don't do the unlock and exit by throwing - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MissingUnlockWithThrow - */ - -/** - * @test id=multiMissingUnlockWithThrow - * @bug 8327743 - * @summary Don't do the unlock and exit by throwing, by multiple threads - * @library /test/lib - * @modules java.base/java.lang:+open - * @requires vm.continuations - * @run driver JNIMonitor MultiMissingUnlockWithThrow - */ - -public class JNIMonitor { - - public static void main(String[] args) throws Exception { - String test = args[0]; - String[] cmdArgs = new String[] { - "-Djava.library.path=" + Utils.TEST_NATIVE_PATH, - // Grant access to ThreadBuilders$VirtualThreadBuilder - "--add-opens=java.base/java.lang=ALL-UNNAMED", - // Enable the JNI warning - "-Xcheck:jni", - "-Xlog:jni=debug", - // Enable thread termination logging as a visual cross-check - "-Xlog:thread+os=info", - // We only count monitors in LM_LEGACY mode - "-XX:LockingMode=1", - // Disable compact headers since that switches locking mode to LM_LIGHTWEIGHT - "-XX:-UseCompactObjectHeaders", - "JNIMonitor$" + test, - }; - OutputAnalyzer oa = ProcessTools.executeTestJava(cmdArgs); - oa.shouldHaveExitValue(0); - oa.stdoutShouldMatch(terminated); - - switch(test) { - case "Normal": - case "MultiNormal": - oa.stdoutShouldNotMatch(stillLocked); - break; - case "MissingUnlock": - oa.stdoutShouldMatch(stillLocked); - break; - case "MultiMissingUnlock": - parseOutputForPattern(oa.stdoutAsLines(), stillLocked, MULTI_THREAD_COUNT); - break; - case "MissingUnlockWithThrow": - oa.stdoutShouldMatch(stillLocked); - oa.stderrShouldContain(throwMsg); - break; - case "MultiMissingUnlockWithThrow": - parseOutputForPattern(oa.stdoutAsLines(), stillLocked, MULTI_THREAD_COUNT); - parseOutputForPattern(oa.stderrAsLines(), throwMsg, MULTI_THREAD_COUNT); - break; - - default: throw new Error("Unknown arg: " + args[0]); - } - oa.reportDiagnosticSummary(); - } - - // The number of threads for a multi tests. Arbitrarily chosen to be > 1 but small - // enough to not waste too much time. - static final int MULTI_THREAD_COUNT = 5; - - // The logging message for leaving a monitor JNI locked has the form - // [0.187s][debug][jni] VirtualThread (tid: 28, carrier id: 29) exiting with Objects still locked by JNI MonitorEnter. - // but if the test is run with other logging options then whitespace may get introduced in the - // log decorator sections, so ignore those. - static final String stillLocked = "VirtualThread \\(tid:.*exiting with Objects still locked by JNI MonitorEnter"; - // The carrier thread termination logging has the form: - // [1.394s][info][os,thread] JavaThread exiting (name: "pool-1-thread-1", tid: 3090592). - static final String terminated = "JavaThread exiting \\(name: \"pool-1-thread-1\""; - - static final String throwMsg = "Terminating via exception as requested"; - - // Check the process logging output for the given pattern to see if the expected number of - // lines are found. - private static void parseOutputForPattern(List lines, String pattern, int expected) { - Pattern p = Pattern.compile(pattern); - int found = 0; - for (String line : lines) { - Matcher m = p.matcher(line); - if (m.find()) { - found++; - } - } - if (found != expected) { - throw new RuntimeException("Checking for pattern \"" + pattern + "\": expected " - + expected + " but found " + found); - } - } - - - // straight-forward interface to JNI monitor functions - static native int monitorEnter(Object o); - static native int monitorExit(Object o); - - // Isolate the native library loading to the actual test cases, not the class that - // jtreg Driver will load and execute. - static class TestBase { - - static { - System.loadLibrary("JNIMonitor"); - } - - // This gives us a way to control the scheduler used for our virtual threads. The test - // only works as intended when the virtual threads run on the same carrier thread (as - // that carrier maintains ownership of the monitor if the virtual thread fails to unlock it). - // The original issue was also only discovered due to the carrier thread terminating - // unexpectedly, so we can force that condition too by shutting down our custom scheduler. - private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) { - Thread.Builder.OfVirtual builder = Thread.ofVirtual(); - try { - Class clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder"); - Constructor ctor = clazz.getDeclaredConstructor(Executor.class); - ctor.setAccessible(true); - return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof RuntimeException re) { - throw re; - } - throw new RuntimeException(e); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - static void runTest(int nThreads, boolean skipUnlock, boolean throwOnExit) throws Throwable { - final Object[] monitors = new Object[nThreads]; - for (int i = 0; i < nThreads; i++) { - monitors[i] = new Object(); - } - final AtomicReference exception = new AtomicReference(); - // Ensure all our VT's operate of the same carrier, sequentially. - ExecutorService scheduler = Executors.newSingleThreadExecutor(); - ThreadFactory factory = virtualThreadBuilder(scheduler).factory(); - for (int i = 0 ; i < nThreads; i++) { - Object monitor = skipUnlock ? monitors[i] : monitors[0]; - Thread th = factory.newThread(() -> { - try { - int res = monitorEnter(monitor); - Asserts.assertTrue(res == 0, "monitorEnter should return 0."); - Asserts.assertTrue(Thread.holdsLock(monitor), "monitor should be owned"); - Thread.yield(); - if (!skipUnlock) { - res = monitorExit(monitor); - Asserts.assertTrue(res == 0, "monitorExit should return 0."); - Asserts.assertFalse(Thread.holdsLock(monitor), "monitor should be unowned"); - } - } catch (Throwable t) { - exception.set(t); - } - if (throwOnExit) { - throw new RuntimeException(throwMsg); - } - }); - th.start(); - th.join(); - if (exception.get() != null) { - throw exception.get(); - } - } - // Now force carrier thread to shutdown. - scheduler.shutdown(); - } - } - - // These are the actual test case classes that get exec'd. - - static class Normal extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(1, false, false); - } - } - - static class MultiNormal extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(MULTI_THREAD_COUNT, false, false); - } - } - - static class MissingUnlock extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(1, true, false); - } - } - - static class MultiMissingUnlock extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(MULTI_THREAD_COUNT, true, false); - } - } - - static class MissingUnlockWithThrow extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(1, true, true); - } - } - - static class MultiMissingUnlockWithThrow extends TestBase { - public static void main(String[] args) throws Throwable { - runTest(MULTI_THREAD_COUNT, true, true); - } - } - -} diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/StopThreadTest/StopThreadTest.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/StopThreadTest/StopThreadTest.java index d455a16c998..4693040fa6b 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/StopThreadTest/StopThreadTest.java +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/StopThreadTest/StopThreadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,9 +46,6 @@ import jdk.test.lib.Platform; import java.lang.AssertionError; -import com.sun.management.HotSpotDiagnosticMXBean; -import java.lang.management.ManagementFactory; - /* * The test exercises the JVMTI function: StopThread(jthread). * The test creates a new virtual or platform thread. @@ -277,8 +274,6 @@ static void C() { } static boolean preemptableVirtualThread() { - boolean legacyLockingMode = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class) - .getVMOption("LockingMode").getValue().equals("1"); - return is_virtual && !isBoundVThread && !legacyLockingMode; + return is_virtual && !isBoundVThread; } } diff --git a/test/jdk/com/sun/jdi/EATests.java b/test/jdk/com/sun/jdi/EATests.java index b2a2cad49db..321855b4969 100644 --- a/test/jdk/com/sun/jdi/EATests.java +++ b/test/jdk/com/sun/jdi/EATests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024 SAP SE. All rights reserved. + * Copyright (c) 2020, 2025 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 @@ -34,42 +34,6 @@ * @run build TestScaffold VMConnection TargetListener TargetAdapter jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run compile -g EATests.java - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 * * @run driver EATests * -XX:+UnlockDiagnosticVMOptions @@ -79,7 +43,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * @run driver EATests * -XX:+UnlockDiagnosticVMOptions * -Xms256m -Xmx256m @@ -88,7 +51,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * @run driver EATests * -XX:+UnlockDiagnosticVMOptions * -Xms256m -Xmx256m @@ -97,7 +59,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * @run driver EATests * -XX:+UnlockDiagnosticVMOptions * -Xms256m -Xmx256m @@ -106,7 +67,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * * @comment Excercise -XX:+DeoptimizeObjectsALot. Mostly to prevent bit-rot because the option is meant to stress object deoptimization * with non-synthetic workloads. @@ -124,16 +84,6 @@ * @comment Regression test for using the wrong thread when logging during re-locking from deoptimization. * * @comment DiagnoseSyncOnValueBasedClasses=2 will cause logging when locking on \@ValueBased objects. - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=1 - * -XX:DiagnoseSyncOnValueBasedClasses=2 * * @comment Re-lock may inflate monitors when re-locking, which cause monitorinflation trace logging. * @run driver EATests @@ -144,23 +94,10 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * -Xlog:monitorinflation=trace:file=monitorinflation.log * - * @comment Re-lock may race with deflation. - * @run driver EATests - * -XX:+UnlockDiagnosticVMOptions - * -Xms256m -Xmx256m - * -Xbootclasspath/a:. - * -XX:CompileCommand=dontinline,*::dontinline_* - * -XX:+WhiteBoxAPI - * -Xbatch - * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=0 - * -XX:GuaranteedAsyncDeflationInterval=1000 - * * @bug 8341819 - * @comment Regression test for re-locking racing with deflation with LM_LIGHTWEIGHT. + * @comment Regression test for re-locking racing with deflation with lightweight locking. * @run driver EATests * -XX:+UnlockDiagnosticVMOptions * -Xms256m -Xmx256m @@ -169,7 +106,6 @@ * -XX:+WhiteBoxAPI * -Xbatch * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks - * -XX:LockingMode=2 * -XX:GuaranteedAsyncDeflationInterval=1 */ @@ -1815,8 +1751,8 @@ 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. + * lightweight the lock stack of the thread will be full because of + * this. */ class EARelockingWithManyLightweightLocks extends EATestCaseBaseDebugger { diff --git a/test/jdk/java/lang/Thread/virtual/CarrierThreadInfo.java b/test/jdk/java/lang/Thread/virtual/CarrierThreadInfo.java index 75ef0376a7e..6260c8e9bda 100644 --- a/test/jdk/java/lang/Thread/virtual/CarrierThreadInfo.java +++ b/test/jdk/java/lang/Thread/virtual/CarrierThreadInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,30 +31,6 @@ * @run junit CarrierThreadInfo */ -/** - * @test id=LM_LIGHTWEIGHT - * @requires vm.continuations - * @modules java.base/java.lang:+open - * @library /test/lib - * @run junit/othervm -XX:LockingMode=2 CarrierThreadInfo - */ - -/** - * @test id=LM_LEGACY - * @requires vm.continuations - * @modules java.base/java.lang:+open - * @library /test/lib - * @run junit/othervm -XX:LockingMode=1 CarrierThreadInfo - */ - -/** - * @test id=LM_MONITOR - * @requires vm.continuations - * @modules java.base/java.lang:+open - * @library /test/lib - * @run junit/othervm -XX:LockingMode=0 CarrierThreadInfo - */ - import java.lang.management.LockInfo; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; diff --git a/test/jdk/java/lang/Thread/virtual/LockingMode.java b/test/jdk/java/lang/Thread/virtual/LockingMode.java deleted file mode 100644 index 59fde4a5f49..00000000000 --- a/test/jdk/java/lang/Thread/virtual/LockingMode.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.lang.management.ManagementFactory; -import com.sun.management.HotSpotDiagnosticMXBean; - -class LockingMode { - private LockingMode() { } - - /** - * Returns true if using legacy locking mode. - */ - static boolean isLegacy() { - return ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class) - .getVMOption("LockingMode") - .getValue() - .equals("1"); - } -} \ No newline at end of file diff --git a/test/jdk/java/lang/Thread/virtual/MiscMonitorTests.java b/test/jdk/java/lang/Thread/virtual/MiscMonitorTests.java index 1f909b214c2..b512aa75789 100644 --- a/test/jdk/java/lang/Thread/virtual/MiscMonitorTests.java +++ b/test/jdk/java/lang/Thread/virtual/MiscMonitorTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test id=default * @summary Tests for object monitors that have been useful to find bugs * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm MiscMonitorTests */ @@ -33,7 +33,7 @@ /* * @test id=Xint * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm -Xint MiscMonitorTests */ @@ -41,7 +41,7 @@ /* * @test id=Xcomp * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm -Xcomp MiscMonitorTests */ @@ -49,7 +49,7 @@ /* * @test id=Xcomp-TieredStopAtLevel3 * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm -Xcomp -XX:TieredStopAtLevel=3 MiscMonitorTests */ @@ -58,14 +58,14 @@ * @test id=Xcomp-noTieredCompilation * @summary Test virtual threads using synchronized * @library /test/lib - * @requires vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.continuations * @modules java.base/java.lang:+open * @run junit/othervm -Xcomp -XX:-TieredCompilation MiscMonitorTests */ /* * @test id=gc - * @requires vm.debug == true & vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.debug == true & vm.continuations * @library /test/lib * @modules java.base/java.lang:+open * @run junit/othervm -XX:+UnlockDiagnosticVMOptions -XX:+FullGCALot -XX:FullGCALotInterval=1000 MiscMonitorTests diff --git a/test/jdk/java/lang/Thread/virtual/MonitorEnterExit.java b/test/jdk/java/lang/Thread/virtual/MonitorEnterExit.java index 858f7625386..3a7eecd054e 100644 --- a/test/jdk/java/lang/Thread/virtual/MonitorEnterExit.java +++ b/test/jdk/java/lang/Thread/virtual/MonitorEnterExit.java @@ -26,88 +26,35 @@ * @summary Test virtual thread with monitor enter/exit * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm/native --enable-native-access=ALL-UNNAMED MonitorEnterExit */ /* - * @test id=LM_LEGACY + * @test id=Xint * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit + * @run junit/othervm/native -Xint --enable-native-access=ALL-UNNAMED MonitorEnterExit */ /* - * @test id=LM_LIGHTWEIGHT + * @test id=Xcomp * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit + * @run junit/othervm/native -Xcomp --enable-native-access=ALL-UNNAMED MonitorEnterExit */ /* - * @test id=Xint-LM_LEGACY + * @test id=Xcomp-TieredStopAtLevel1 * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xint -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit + * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit */ /* - * @test id=Xint-LM_LIGHTWEIGHT + * @test id=Xcomp-noTieredCompilation * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xint -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-TieredStopAtLevel1-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-TieredStopAtLevel1-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-noTieredCompilation-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:-TieredCompilation -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorEnterExit - */ - -/* - * @test id=Xcomp-noTieredCompilation-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:-TieredCompilation -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorEnterExit + * @run junit/othervm/native -Xcomp -XX:-TieredCompilation --enable-native-access=ALL-UNNAMED MonitorEnterExit */ import java.time.Duration; @@ -129,7 +76,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.RepeatedTest; -import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.ValueSource; @@ -234,7 +180,6 @@ private void testReenter(Object lock, int depth) { * Test monitor reenter when there are other threads blocked trying to enter. */ @Test - @DisabledIf("LockingMode#isLegacy") void testReenterWithContention() throws Exception { var lock = new Object(); VThreadRunner.run(() -> { @@ -359,7 +304,6 @@ private void testEnterWithContentionWhenPinned() throws Exception { * Test that blocking waiting to enter a monitor releases the carrier. */ @Test - @DisabledIf("LockingMode#isLegacy") void testReleaseWhenBlocked() throws Exception { assumeTrue(VThreadScheduler.supportsCustomScheduler(), "No support for custom schedulers"); try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { @@ -403,7 +347,6 @@ void testReleaseWhenBlocked() throws Exception { * carriers aren't released. */ @Test - @DisabledIf("LockingMode#isLegacy") void testManyBlockedThreads() throws Exception { Thread[] vthreads = new Thread[MAX_VTHREAD_COUNT]; var lock = new Object(); diff --git a/test/jdk/java/lang/Thread/virtual/MonitorWaitNotify.java b/test/jdk/java/lang/Thread/virtual/MonitorWaitNotify.java index 0ec0adb0faf..d5df8eb97d0 100644 --- a/test/jdk/java/lang/Thread/virtual/MonitorWaitNotify.java +++ b/test/jdk/java/lang/Thread/virtual/MonitorWaitNotify.java @@ -26,88 +26,35 @@ * @summary Test virtual threads using Object.wait/notifyAll * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm/native --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ /* - * @test id=LM_LEGACY + * @test id=Xint * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify + * @run junit/othervm/native -Xint --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ /* - * @test id=LM_LIGHTWEIGHT + * @test id=Xcomp * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify + * @run junit/othervm/native -Xcomp --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ /* - * @test id=Xint-LM_LEGACY + * @test id=Xcomp-TieredStopAtLevel1 * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xint -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify + * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ /* - * @test id=Xint-LM_LIGHTWEIGHT + * @test id=Xcomp-noTieredCompilation * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xint -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-TieredStopAtLevel1-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-TieredStopAtLevel1-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:TieredStopAtLevel=1 -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-noTieredCompilation-LM_LEGACY - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:-TieredCompilation -XX:LockingMode=1 --enable-native-access=ALL-UNNAMED MonitorWaitNotify - */ - -/* - * @test id=Xcomp-noTieredCompilation-LM_LIGHTWEIGHT - * @modules java.base/java.lang:+open jdk.management - * @library /test/lib - * @build LockingMode - * @run junit/othervm/native -Xcomp -XX:-TieredCompilation -XX:LockingMode=2 --enable-native-access=ALL-UNNAMED MonitorWaitNotify + * @run junit/othervm/native -Xcomp -XX:-TieredCompilation --enable-native-access=ALL-UNNAMED MonitorWaitNotify */ import java.util.ArrayList; @@ -131,7 +78,6 @@ import jdk.test.lib.thread.VThreadPinner; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; @@ -306,7 +252,6 @@ static Stream threadCounts() { */ @ParameterizedTest @MethodSource("threadCounts") - @DisabledIf("LockingMode#isLegacy") void testNotifyOneThread(int nPlatformThreads, int nVirtualThreads) throws Exception { int nThreads = nPlatformThreads + nVirtualThreads; @@ -364,7 +309,6 @@ void testNotifyOneThread(int nPlatformThreads, int nVirtualThreads) throws Excep */ @ParameterizedTest @MethodSource("threadCounts") - @DisabledIf("LockingMode#isLegacy") void testNotifyAllThreads(int nPlatformThreads, int nVirtualThreads) throws Exception { int nThreads = nPlatformThreads + nVirtualThreads; @@ -702,7 +646,6 @@ void testParkingPermitNotOffered() throws Exception { */ @ParameterizedTest @ValueSource(ints = { 0, 30000, Integer.MAX_VALUE }) - @DisabledIf("LockingMode#isLegacy") void testReleaseWhenWaiting1(int timeout) throws Exception { assumeTrue(VThreadScheduler.supportsCustomScheduler(), "No support for custom schedulers"); try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { @@ -759,7 +702,6 @@ void testReleaseWhenWaiting1(int timeout) throws Exception { */ @ParameterizedTest @ValueSource(ints = { 0, 10, 20, 100, 500, 30000, Integer.MAX_VALUE }) - @DisabledIf("LockingMode#isLegacy") void testReleaseWhenWaiting2(int timeout) throws Exception { int VTHREAD_COUNT = 4 * Runtime.getRuntime().availableProcessors(); CountDownLatch latch = new CountDownLatch(VTHREAD_COUNT); diff --git a/test/jdk/java/lang/Thread/virtual/Parking.java b/test/jdk/java/lang/Thread/virtual/Parking.java index 41f7f283bdd..574707e637c 100644 --- a/test/jdk/java/lang/Thread/virtual/Parking.java +++ b/test/jdk/java/lang/Thread/virtual/Parking.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * @summary Test virtual threads using park/unpark * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit Parking */ @@ -34,7 +33,6 @@ * @test id=Xint * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm -Xint Parking */ @@ -42,7 +40,6 @@ * @test id=Xcomp * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm -Xcomp Parking */ @@ -50,7 +47,6 @@ * @test id=Xcomp-noTieredCompilation * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm -Xcomp -XX:-TieredCompilation Parking */ @@ -66,7 +62,6 @@ import jdk.test.lib.thread.VThreadRunner; import jdk.test.lib.thread.VThreadScheduler; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import static org.junit.jupiter.api.Assertions.*; @@ -385,7 +380,6 @@ void testParkNanos11() throws Exception { */ @ParameterizedTest @ValueSource(booleans = { true, false }) - @DisabledIf("LockingMode#isLegacy") void testParkWhenHoldingMonitor(boolean reenter) throws Exception { assumeTrue(VThreadScheduler.supportsCustomScheduler(), "No support for custom schedulers"); try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { @@ -435,7 +429,6 @@ void testParkWhenHoldingMonitor(boolean reenter) throws Exception { * parking doesn't release the carrier. */ @Test - @DisabledIf("LockingMode#isLegacy") void testManyParkedWhenHoldingMonitor() throws Exception { Thread[] vthreads = new Thread[MAX_VTHREAD_COUNT]; var done = new AtomicBoolean(); diff --git a/test/jdk/java/lang/Thread/virtual/RetryMonitorEnterWhenPinned.java b/test/jdk/java/lang/Thread/virtual/RetryMonitorEnterWhenPinned.java index fa754a88b80..1c7177d9f38 100644 --- a/test/jdk/java/lang/Thread/virtual/RetryMonitorEnterWhenPinned.java +++ b/test/jdk/java/lang/Thread/virtual/RetryMonitorEnterWhenPinned.java @@ -29,7 +29,6 @@ * can't continue because there are no carriers available. * @modules java.base/java.lang:+open * @library /test/lib - * @requires vm.opt.LockingMode != 1 * @run main/othervm/native --enable-native-access=ALL-UNNAMED RetryMonitorEnterWhenPinned */ diff --git a/test/jdk/java/lang/Thread/virtual/ThreadAPI.java b/test/jdk/java/lang/Thread/virtual/ThreadAPI.java index a3d85660b99..b7fdeb8ec84 100644 --- a/test/jdk/java/lang/Thread/virtual/ThreadAPI.java +++ b/test/jdk/java/lang/Thread/virtual/ThreadAPI.java @@ -27,7 +27,6 @@ * @summary Test Thread API with virtual threads * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm/native --enable-native-access=ALL-UNNAMED ThreadAPI */ @@ -36,7 +35,6 @@ * @requires vm.continuations * @modules java.base/java.lang:+open jdk.management * @library /test/lib - * @build LockingMode * @run junit/othervm/native -XX:+UnlockExperimentalVMOptions -XX:-VMContinuations * --enable-native-access=ALL-UNNAMED ThreadAPI */ @@ -70,7 +68,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.ValueSource; @@ -1112,7 +1109,6 @@ void testYieldReleasesCarrier() throws Exception { * Test Thread.yield releases carrier thread when virtual thread holds a monitor. */ @Test - @DisabledIf("LockingMode#isLegacy") void testYieldReleasesCarrierWhenHoldingMonitor() throws Exception { assumeTrue(VThreadScheduler.supportsCustomScheduler(), "No support for custom schedulers"); var list = new CopyOnWriteArrayList(); diff --git a/test/jdk/java/lang/Thread/virtual/stress/LotsOfContendedMonitorEnter.java b/test/jdk/java/lang/Thread/virtual/stress/LotsOfContendedMonitorEnter.java index c63a4b0c947..da45c610e82 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/LotsOfContendedMonitorEnter.java +++ b/test/jdk/java/lang/Thread/virtual/stress/LotsOfContendedMonitorEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,18 +24,10 @@ /* * @test id=default * @summary Test virtual threads entering a lot of monitors with contention - * @requires vm.opt.LockingMode != 1 * @library /test/lib * @run main LotsOfContendedMonitorEnter */ -/* - * @test id=LM_LIGHTWEIGHT - * @requires vm.opt.LockingMode != 1 - * @library /test/lib - * @run main/othervm -XX:LockingMode=2 LotsOfContendedMonitorEnter - */ - import java.util.concurrent.CountDownLatch; import jdk.test.lib.thread.VThreadRunner; diff --git a/test/jdk/java/lang/Thread/virtual/stress/LotsOfUncontendedMonitorEnter.java b/test/jdk/java/lang/Thread/virtual/stress/LotsOfUncontendedMonitorEnter.java index da5fdd1161d..e1a8fb82bd6 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/LotsOfUncontendedMonitorEnter.java +++ b/test/jdk/java/lang/Thread/virtual/stress/LotsOfUncontendedMonitorEnter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,18 +28,6 @@ * @run main LotsOfUncontendedMonitorEnter */ -/* - * @test id=LM_LEGACY - * @library /test/lib - * @run main/othervm -XX:LockingMode=1 LotsOfUncontendedMonitorEnter - */ - -/* - * @test id=LM_LIGHTWEIGHT - * @library /test/lib - * @run main/othervm -XX:LockingMode=2 LotsOfUncontendedMonitorEnter - */ - import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; diff --git a/test/jdk/java/lang/Thread/virtual/stress/Skynet100kWithMonitors.java b/test/jdk/java/lang/Thread/virtual/stress/Skynet100kWithMonitors.java index 9487de6b862..7949529af60 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/Skynet100kWithMonitors.java +++ b/test/jdk/java/lang/Thread/virtual/stress/Skynet100kWithMonitors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,13 @@ * @summary Stress test virtual threads with a variation of the Skynet 1M benchmark that uses * a channel implementation based on object monitors. This variant uses a reduced number of * 100k virtual threads at the final level. - * @requires vm.debug != true & vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.debug != true & vm.continuations * @run main/othervm/timeout=300 Skynet100kWithMonitors 50 */ /* * @test - * @requires vm.debug == true & vm.continuations & vm.opt.LockingMode != 1 + * @requires vm.debug == true & vm.continuations * @run main/othervm/timeout=300 Skynet100kWithMonitors 10 */ diff --git a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java index b8e9a1736c4..0f52bc67f08 100644 --- a/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java +++ b/test/jdk/java/util/concurrent/ConcurrentHashMap/MapLoops.java @@ -45,15 +45,6 @@ * @run main/timeout=1600 MapLoops */ -/* - * @test - * @summary Exercise multithreaded maps, using only heavy monitors. - * @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64" | os.arch == "s390x" - * @requires vm.debug - * @library /test/lib - * @run main/othervm/timeout=1600 -XX:LockingMode=0 -XX:+VerifyHeavyMonitors MapLoops - */ - import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.List; diff --git a/test/jdk/jdk/internal/vm/Continuation/Basic.java b/test/jdk/jdk/internal/vm/Continuation/Basic.java index e13fa175ad5..393c30a3cc9 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Basic.java +++ b/test/jdk/jdk/internal/vm/Continuation/Basic.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,9 +64,6 @@ import java.util.stream.Collectors; import java.util.stream.IntStream; -import com.sun.management.HotSpotDiagnosticMXBean; -import java.lang.management.ManagementFactory; - import org.testng.annotations.Test; import org.testng.annotations.DataProvider; import static org.testng.Assert.*; @@ -281,39 +278,6 @@ static String barMany(long b, return "" + r; } - @Test - public void testPinnedMonitor() { - if (!legacyLockingMode()) return; - - // Test pinning due to held monitor - final AtomicReference res = new AtomicReference<>(); - - Continuation cont = new Continuation(FOO, ()-> { - syncFoo(1); - }) { - @Override - protected void onPinned(Continuation.Pinned reason) { - assert Continuation.isPinned(FOO); - res.set(reason); - } - }; - - cont.run(); - assertEquals(res.get(), Continuation.Pinned.MONITOR); - boolean isDone = cont.isDone(); - assertEquals(isDone, true); - } - - static double syncFoo(int a) { - long x = 8; - String s = "yyy"; - String r; - synchronized(FOO) { - r = bar2(a + 1); - } - return Integer.parseInt(r)+1; - } - @Test public void testNotPinnedMonitor() { final AtomicReference res = new AtomicReference<>(); @@ -419,9 +383,4 @@ static int nativeBaz(int b) { static { System.loadLibrary("BasicJNI"); } - - static boolean legacyLockingMode() { - return ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class) - .getVMOption("LockingMode").getValue().equals("1"); - } } diff --git a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java index 52730c9523b..5f4f8c85f61 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java +++ b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java @@ -1,5 +1,5 @@ /* -* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -473,7 +473,8 @@ void verifyResult(int result) { } boolean shouldPin() { - return traceHas(Op.PIN::contains) && legacyLockingMode(); + // Returns false since we never pin after we removed legacy locking. + return traceHas(Op.PIN::contains) && false; } void verifyPin(boolean yieldResult) { @@ -1032,9 +1033,4 @@ int com_mny(int depth, return log((int)res); } - - static boolean legacyLockingMode() { - return ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class) - .getVMOption("LockingMode").getValue().equals("1"); - } } diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 3c7a81cd2fa..681c88654c0 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -118,8 +118,6 @@ public Map call() { map.put("vm.jvmti", this::vmHasJVMTI); map.put("vm.cpu.features", this::cpuFeatures); map.put("vm.pageSize", this::vmPageSize); - map.put("vm.rtm.cpu", this::vmRTMCPU); - map.put("vm.rtm.compiler", this::vmRTMCompiler); // vm.cds is true if the VM is compiled with cds support. map.put("vm.cds", this::vmCDS); map.put("vm.cds.custom.loaders", this::vmCDSForCustomLoaders); @@ -417,28 +415,6 @@ protected String vmHasDTrace() { return "" + WB.isDTraceIncluded(); } - /** - * @return "true" if compiler in use supports RTM and "false" otherwise. - * Note: Lightweight locking does not support RTM (for now). - */ - protected String vmRTMCompiler() { - boolean isRTMCompiler = false; - - if (Compiler.isC2Enabled() && - (Platform.isX86() || Platform.isX64() || Platform.isPPC()) && - is_LM_LIGHTWEIGHT().equals("false")) { - isRTMCompiler = true; - } - return "" + isRTMCompiler; - } - - /** - * @return true if VM runs RTM supported CPU and false otherwise. - */ - protected String vmRTMCPU() { - return "" + CPUInfo.hasFeature("rtm"); - } - /** * Check for CDS support. * @@ -532,34 +508,6 @@ protected String vmPageSize() { return "" + WB.getVMPageSize(); } - /** - * @return LockingMode. - */ - protected String vmLockingMode() { - return "" + WB.getIntVMFlag("LockingMode"); - } - - /** - * @return "true" if LockingMode == 0 (LM_MONITOR) - */ - protected String is_LM_MONITOR() { - return "" + vmLockingMode().equals("0"); - } - - /** - * @return "true" if LockingMode == 1 (LM_LEGACY) - */ - protected String is_LM_LEGACY() { - return "" + vmLockingMode().equals("1"); - } - - /** - * @return "true" if LockingMode == 2 (LM_LIGHTWEIGHT) - */ - protected String is_LM_LIGHTWEIGHT() { - return "" + vmLockingMode().equals("2"); - } - /** * Check if Graal is used as JIT compiler. * From 5a1301df19553c7ba04c746b4002164f3b833e70 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 26 Jun 2025 09:15:32 +0000 Subject: [PATCH 187/213] 8360548: Parallel: Remove outdated comments in MutableNUMASpace::bias_region Reviewed-by: tschatzl --- src/hotspot/share/gc/parallel/mutableNUMASpace.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 7ab515fffb4..122f4945ec3 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -201,8 +201,6 @@ void MutableNUMASpace::bias_region(MemRegion mr, uint lgrp_id) { const size_t os_align = UseLargePages ? page_size() : os::vm_page_size(); os::realign_memory((char*)aligned_region.start(), aligned_region.byte_size(), os_align); // Then we uncommit the pages in the range. - // The alignment_hint argument must be less than or equal to the small page - // size if not using large pages or else this function does nothing. os::disclaim_memory((char*)aligned_region.start(), aligned_region.byte_size()); // And make them local/first-touch biased. os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size(), checked_cast(lgrp_id)); From ff24088c866864fa670bbfdd068b1a50b6bcf0db Mon Sep 17 00:00:00 2001 From: Doug Lea Date: Thu, 26 Jun 2025 12:04:42 +0000 Subject: [PATCH 188/213] =?UTF-8?q?8359919:=20Minor=20java.util.concurrent?= =?UTF-8?q?=20doc=20improvements=208187775:=20AtomicReferenceFieldUpdater?= =?UTF-8?q?=20does=20not=20support=20static=20fields=208254060:=20Submissi?= =?UTF-8?q?onPublisher=20close=20hangs=20if=20a=20publication=20is=20pendi?= =?UTF-8?q?ng=208210149:=20Example=20in=20JavaDoc=20for=20java.util.concur?= =?UTF-8?q?rent.Flow=20violates=20Reactive=20Streams=20spec=208199501:=20I?= =?UTF-8?q?mprove=20documentation=20of=20CompletableFuture,=20CompletionSt?= =?UTF-8?q?age=208233050:=20CompletableFuture=20`whenComplete`=20and=20`th?= =?UTF-8?q?enApply`=20change=20exceptional=20result=208210312:=20JavaDoc?= =?UTF-8?q?=20example=20in=20SubmissionPublisher=20will=20potentially=20cr?= =?UTF-8?q?ash=208292365:=20CompletableFuture=20and=20CompletionStage=20sh?= =?UTF-8?q?ould=20document=20Memory=20Model=20guarantees=208356304:=20Defi?= =?UTF-8?q?ne=20"enabled"=20in=20ScheduledExecutorService=208353155:=20Fut?= =?UTF-8?q?ureTask#run():=20doc=20implies=20synchronous,=20implementation?= =?UTF-8?q?=20is=20async=208186959:=20Clarify=20that=20Executors.newSchedu?= =?UTF-8?q?ledThreadPool()=20is=20fixed-size=208190889:=20TimeUnit.wait=20?= =?UTF-8?q?should=20document=20IllegalMonitorStateException=206351533:=20C?= =?UTF-8?q?yclicBarrier=20reset()=20should=20return=20the=20number=20of=20?= =?UTF-8?q?awaiters=206317534:=20CyclicBarrier=20should=20have=20a=20cance?= =?UTF-8?q?l()=20method=208195628:=20Documentation=20for=20lock(),=20trylo?= =?UTF-8?q?ck(),=20lockInterruptibly=E2=80=8B()=20=20of=20ReentrantReadWri?= =?UTF-8?q?teLock.WriteLock=20needs=20to=20be=20corrected=208333172:=20Doc?= =?UTF-8?q?ument=20a=20recommendation=20to=20use=20VarHandles=20instead=20?= =?UTF-8?q?of=20java.util.concurrent.atomic.*FieldUpdater=206374942:=20Imp?= =?UTF-8?q?rove=20thread=20safety=20of=20collection=20.equals()=20methods?= =?UTF-8?q?=207176957:=20ExecutorService=20submit=20method=20javaDoc=20enh?= =?UTF-8?q?ancement=208172177:=20Improve=20documentation=20for=20Completio?= =?UTF-8?q?nException=20handling=206714849:=20ReentrantReadWriteLock:=20Ab?= =?UTF-8?q?normal=20behavior=20in=20non-fair=20mode=206625724:=20Allow=20R?= =?UTF-8?q?eentrantReadWriteLock=20to=20not=20track=20per-thread=20read=20?= =?UTF-8?q?holds=206526284:=20Improve=20AbstractExecutorService=20javadoc?= =?UTF-8?q?=208137156:=20Javadoc=20for=20Future=20is=20misleading=20with?= =?UTF-8?q?=20respect=20to=20cancellation=206663476:=20FutureTask.get()=20?= =?UTF-8?q?may=20return=20null=20if=20set()=20is=20not=20called=20from=20r?= =?UTF-8?q?un()=208311131:=20ConcurrentHashMap.forEachKey=20parallelismThr?= =?UTF-8?q?eshold=20description=20could=20be=20clearer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: alanb --- .../concurrent/AbstractExecutorService.java | 20 +- .../java/util/concurrent/CompletionStage.java | 268 +++++++++--------- .../util/concurrent/ConcurrentHashMap.java | 64 ++--- .../java/util/concurrent/CyclicBarrier.java | 5 +- .../java/util/concurrent/ExecutorService.java | 4 +- .../java/util/concurrent/Executors.java | 4 +- .../classes/java/util/concurrent/Flow.java | 3 +- .../java/util/concurrent/ForkJoinPool.java | 12 +- .../classes/java/util/concurrent/Future.java | 20 ++ .../java/util/concurrent/FutureTask.java | 4 +- .../java/util/concurrent/RunnableFuture.java | 5 +- .../concurrent/ScheduledExecutorService.java | 18 +- .../ScheduledThreadPoolExecutor.java | 6 +- .../util/concurrent/SubmissionPublisher.java | 10 +- .../java/util/concurrent/TimeUnit.java | 2 + .../atomic/AtomicIntegerFieldUpdater.java | 9 +- .../atomic/AtomicLongFieldUpdater.java | 9 +- .../atomic/AtomicReferenceFieldUpdater.java | 31 +- .../locks/ReentrantReadWriteLock.java | 28 +- .../java/util/concurrent/package-info.java | 4 +- 20 files changed, 304 insertions(+), 222 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java b/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java index 0d26607591d..c249f630163 100644 --- a/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java +++ b/src/java.base/share/classes/java/util/concurrent/AbstractExecutorService.java @@ -44,16 +44,16 @@ import java.util.Objects; /** - * Provides default implementations of {@link ExecutorService} - * execution methods. This class implements the {@code submit}, - * {@code invokeAny} and {@code invokeAll} methods using a - * {@link RunnableFuture} returned by {@code newTaskFor}, which defaults - * to the {@link FutureTask} class provided in this package. For example, - * the implementation of {@code submit(Runnable)} creates an - * associated {@code RunnableFuture} that is executed and - * returned. Subclasses may override the {@code newTaskFor} methods - * to return {@code RunnableFuture} implementations other than - * {@code FutureTask}. + * Provides default implementations of {@link ExecutorService} methods + * other than {@link Executor#execute}. This class implements the {@code + * submit}, {@code invokeAny} and {@code invokeAll} methods using a + * {@link RunnableFuture} returned by {@code newTaskFor}, which + * defaults to the {@link FutureTask} class provided in this package. + * For example, the implementation of {@code submit(Runnable)} creates + * an associated {@code RunnableFuture} that is executed and + * returned. Subclasses may override the {@code newTaskFor} methods to + * return {@code RunnableFuture} implementations other than {@code + * FutureTask}. * *

    Extension example. Here is a sketch of a class * that customizes {@link ThreadPoolExecutor} to use diff --git a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java index 6ff31c61049..b4368842865 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletionStage.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletionStage.java @@ -43,7 +43,7 @@ /** * A stage of a possibly asynchronous computation, that performs an * action or computes a value when another CompletionStage completes. - * A stage completes upon termination of its computation, but this may + * A stage completes upon termination of its computation, which may * in turn trigger other dependent stages. The functionality defined * in this interface takes only a few basic forms, which expand out to * a larger set of methods to capture a range of usage styles: @@ -97,18 +97,25 @@ * In all other cases, if a stage's computation terminates abruptly * with an (unchecked) exception or error, then all dependent stages * requiring its completion complete exceptionally as well, with a - * {@link CompletionException} holding the exception as its cause. If - * a stage is dependent on both of two stages, and both - * complete exceptionally, then the CompletionException may correspond - * to either one of these exceptions. If a stage is dependent on - * either of two others, and only one of them completes - * exceptionally, no guarantees are made about whether the dependent - * stage completes normally or exceptionally. In the case of method - * {@code whenComplete}, when the supplied action itself encounters an - * exception, then the stage completes exceptionally with this - * exception unless the source stage also completed exceptionally, in - * which case the exceptional completion from the source stage is - * given preference and propagated to the dependent stage. + * {@link CompletionException} holding the exception as its + * cause. This convention distinguishes exceptions in an action itself + * from those it depends on. If they are to be handled in the same + * way, instead catch {@link RuntimeException} (possibly inspecting + * the exception's {@code getCause()}). If a stage is dependent on + * both of two stages, and both complete exceptionally, then + * the CompletionException may correspond to either one of these + * exceptions. If a stage is dependent on either of two + * others, and only one of them completes exceptionally, no guarantees + * are made about whether the dependent stage completes normally or + * exceptionally. In the case of method {@code whenComplete}, when the + * supplied action itself encounters an exception, then the stage + * completes exceptionally with that exception unless the source stage + * also completed exceptionally, in which case the exceptional + * completion from the source stage is given preference and propagated + * to the dependent stage. Applications are encouraged to maintain + * these conventions, avoiding unnecessary nesting when rethrowing, as + * in {@code throw (ex instanceof CompletionException) ? ex : new + * CompletionException(ex)}. * * * @@ -137,7 +144,7 @@ * } * }} * - *

    This interface does not define methods for initially creating, + *

    The {@code CompletionStage} interface does not define methods for initially creating, * forcibly completing normally or exceptionally, probing completion * status or results, or awaiting completion of a stage. * Implementations of CompletionStage may provide means of achieving @@ -145,6 +152,13 @@ * enables interoperability among different implementations of this * interface by providing a common conversion type. * + *

    Memory consistency effects: Actions in a thread prior to the + * submission of a computation producing a {@code CompletionStage} happen-before + * that computation begins. And actions taken by {@code + * CompletionStage x} happen-before actions of any dependent + * stage subsequent to {@code x}'s completion. + * * @param the type of values the stage produces or consumes * * @author Doug Lea @@ -153,8 +167,8 @@ public interface CompletionStage { /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed with this stage's result as the argument + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed with {@code this} stage's result as the argument * to the supplied function. * *

    This method is analogous to @@ -172,9 +186,9 @@ public interface CompletionStage { public CompletionStage thenApply(Function fn); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using this stage's default asynchronous - * execution facility, with this stage's result as the argument to + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using {@code this} stage's default asynchronous + * execution facility, with {@code this} stage's result as the argument to * the supplied function. * * See the {@link CompletionStage} documentation for rules @@ -189,8 +203,8 @@ public interface CompletionStage { (Function fn); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using the supplied Executor, with this + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using the supplied Executor, with {@code this} * stage's result as the argument to the supplied function. * * See the {@link CompletionStage} documentation for rules @@ -207,8 +221,8 @@ public interface CompletionStage { Executor executor); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed with this stage's result as the argument + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed with {@code this} stage's result as the argument * to the supplied action. * * See the {@link CompletionStage} documentation for rules @@ -221,9 +235,9 @@ public interface CompletionStage { public CompletionStage thenAccept(Consumer action); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using this stage's default asynchronous - * execution facility, with this stage's result as the argument to + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using {@code this} stage's default asynchronous + * execution facility, with {@code this} stage's result as the argument to * the supplied action. * * See the {@link CompletionStage} documentation for rules @@ -236,8 +250,8 @@ public interface CompletionStage { public CompletionStage thenAcceptAsync(Consumer action); /** - * Returns a new CompletionStage that, when this stage completes - * normally, is executed using the supplied Executor, with this + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, is executed using the supplied Executor, with {@code this} * stage's result as the argument to the supplied action. * * See the {@link CompletionStage} documentation for rules @@ -251,7 +265,7 @@ public interface CompletionStage { public CompletionStage thenAcceptAsync(Consumer action, Executor executor); /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * normally, executes the given action. * * See the {@link CompletionStage} documentation for rules @@ -264,8 +278,8 @@ public CompletionStage thenAcceptAsync(Consumer action, public CompletionStage thenRun(Runnable action); /** - * Returns a new CompletionStage that, when this stage completes - * normally, executes the given action using this stage's default + * Returns a new CompletionStage that, when {@code this} stage completes + * normally, executes the given action using {@code this} stage's default * asynchronous execution facility. * * See the {@link CompletionStage} documentation for rules @@ -278,7 +292,7 @@ public CompletionStage thenAcceptAsync(Consumer action, public CompletionStage thenRunAsync(Runnable action); /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * normally, executes the given action using the supplied Executor. * * See the {@link CompletionStage} documentation for rules @@ -293,7 +307,7 @@ public CompletionStage thenRunAsync(Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed with the two * results as arguments to the supplied function. * @@ -312,8 +326,8 @@ public CompletionStage thenRunAsync(Runnable action, BiFunction fn); /** - * Returns a new CompletionStage that, when this and the other - * given stage both complete normally, is executed using this + * Returns a new CompletionStage that, when {@code this} and the other + * given stage both complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the two * results as arguments to the supplied function. * @@ -332,7 +346,7 @@ public CompletionStage thenRunAsync(Runnable action, BiFunction fn); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed using the * supplied executor, with the two results as arguments to the * supplied function. @@ -354,7 +368,7 @@ public CompletionStage thenRunAsync(Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed with the two * results as arguments to the supplied action. * @@ -372,8 +386,8 @@ public CompletionStage thenRunAsync(Runnable action, BiConsumer action); /** - * Returns a new CompletionStage that, when this and the other - * given stage both complete normally, is executed using this + * Returns a new CompletionStage that, when {@code this} and the other + * given stage both complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the two * results as arguments to the supplied action. * @@ -391,7 +405,7 @@ public CompletionStage thenRunAsync(Runnable action, BiConsumer action); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, is executed using the * supplied executor, with the two results as arguments to the * supplied action. @@ -412,7 +426,7 @@ public CompletionStage thenRunAsync(Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, executes the given action. * * See the {@link CompletionStage} documentation for rules @@ -426,9 +440,9 @@ public CompletionStage thenRunAsync(Runnable action, public CompletionStage runAfterBoth(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, executes the given action - * using this stage's default asynchronous execution facility. + * using {@code this} stage's default asynchronous execution facility. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -442,7 +456,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when this and the other + * Returns a new CompletionStage that, when {@code this} and the other * given stage both complete normally, executes the given action * using the supplied executor. * @@ -459,7 +473,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Runnable action, Executor executor); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed with the * corresponding result as argument to the supplied function. * @@ -477,8 +491,8 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Function fn); /** - * Returns a new CompletionStage that, when either this or the - * other given stage complete normally, is executed using this + * Returns a new CompletionStage that, when either {@code this} or the + * other given stage complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the * corresponding result as argument to the supplied function. * @@ -496,7 +510,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Function fn); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed using the * supplied executor, with the corresponding result as argument to * the supplied function. @@ -517,7 +531,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed with the * corresponding result as argument to the supplied action. * @@ -534,8 +548,8 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Consumer action); /** - * Returns a new CompletionStage that, when either this or the - * other given stage complete normally, is executed using this + * Returns a new CompletionStage that, when either {@code this} or the + * other given stage complete normally, is executed using {@code this} * stage's default asynchronous execution facility, with the * corresponding result as argument to the supplied action. * @@ -552,7 +566,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Consumer action); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, is executed using the * supplied executor, with the corresponding result as argument to * the supplied action. @@ -572,7 +586,7 @@ public CompletionStage runAfterBothAsync(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, executes the given action. * * See the {@link CompletionStage} documentation for rules @@ -587,9 +601,9 @@ public CompletionStage runAfterEither(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, executes the given action - * using this stage's default asynchronous execution facility. + * using {@code this} stage's default asynchronous execution facility. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -604,7 +618,7 @@ public CompletionStage runAfterEither(CompletionStage other, Runnable action); /** - * Returns a new CompletionStage that, when either this or the + * Returns a new CompletionStage that, when either {@code this} or the * other given stage complete normally, executes the given action * using the supplied executor. * @@ -626,10 +640,10 @@ public CompletionStage runAfterEither(CompletionStage other, * Returns a new CompletionStage that is completed with the same * value as the CompletionStage returned by the given function. * - *

    When this stage completes normally, the given function is - * invoked with this stage's result as the argument, returning + *

    When {@code this} stage completes normally, the given function is + * invoked with {@code this} stage's result as the argument, returning * another CompletionStage. When that stage completes normally, - * the CompletionStage returned by this method is completed with + * the CompletionStage returned is completed with * the same value. * *

    To ensure progress, the supplied function must arrange @@ -652,13 +666,13 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage that is completed with the same * value as the CompletionStage returned by the given function, - * executed using this stage's default asynchronous execution + * executed using {@code this} stage's default asynchronous execution * facility. * - *

    When this stage completes normally, the given function is - * invoked with this stage's result as the argument, returning + *

    When {@code this} stage completes normally, the given function is + * invoked with {@code this} stage's result as the argument, returning * another CompletionStage. When that stage completes normally, - * the CompletionStage returned by this method is completed with + * the CompletionStage returned is completed with * the same value. * *

    To ensure progress, the supplied function must arrange @@ -679,10 +693,10 @@ public CompletionStage runAfterEither(CompletionStage other, * value as the CompletionStage returned by the given function, * executed using the supplied Executor. * - *

    When this stage completes normally, the given function is - * invoked with this stage's result as the argument, returning + *

    When {@code this} stage completes normally, the given function is + * invoked with {@code this} stage's result as the argument, returning * another CompletionStage. When that stage completes normally, - * the CompletionStage returned by this method is completed with + * the CompletionStage returned by {@code this} method is completed with * the same value. * *

    To ensure progress, the supplied function must arrange @@ -701,13 +715,13 @@ public CompletionStage runAfterEither(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when this stage completes - * either normally or exceptionally, is executed with this stage's + * Returns a new CompletionStage that, when {@code this} stage completes + * either normally or exceptionally, is executed with {@code this} stage's * result and exception as arguments to the supplied function. * - *

    When this stage is complete, the given function is invoked + *

    When {@code this} stage is complete, the given function is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments, and the + * {@code null} if none) of {@code this} stage as arguments, and the * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the @@ -719,14 +733,14 @@ public CompletionStage runAfterEither(CompletionStage other, (BiFunction fn); /** - * Returns a new CompletionStage that, when this stage completes - * either normally or exceptionally, is executed using this stage's - * default asynchronous execution facility, with this stage's + * Returns a new CompletionStage that, when {@code this} stage completes + * either normally or exceptionally, is executed using {@code this} stage's + * default asynchronous execution facility, with {@code this} stage's * result and exception as arguments to the supplied function. * - *

    When this stage is complete, the given function is invoked + *

    When {@code this} stage is complete, the given function is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments, and the + * {@code null} if none) of {@code this} stage as arguments, and the * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the @@ -738,14 +752,14 @@ public CompletionStage runAfterEither(CompletionStage other, (BiFunction fn); /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * either normally or exceptionally, is executed using the - * supplied executor, with this stage's result and exception as + * supplied executor, with {@code this} stage's result and exception as * arguments to the supplied function. * - *

    When this stage is complete, the given function is invoked + *

    When {@code this} stage is complete, the given function is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments, and the + * {@code null} if none) of {@code this} stage as arguments, and the * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the @@ -760,22 +774,22 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage with the same result or exception as - * this stage, that executes the given action when this stage completes. + * {@code this} stage, that executes the given action when {@code this} stage completes. * - *

    When this stage is complete, the given action is invoked + *

    When {@code this} stage is complete, the given action is invoked * with the result (or {@code null} if none) and the exception (or - * {@code null} if none) of this stage as arguments. The returned + * {@code null} if none) of {@code this} stage as arguments. The returned * stage is completed when the action returns. * *

    Unlike method {@link #handle handle}, - * this method is not designed to translate completion outcomes, + * method {@code whenComplete} is not designed to translate completion outcomes, * so the supplied action should not throw an exception. However, - * if it does, the following rules apply: if this stage completed + * if it does, the following rules apply: if {@code this} stage completed * normally but the supplied action throws an exception, then the * returned stage completes exceptionally with the supplied - * action's exception. Or, if this stage completed exceptionally + * action's exception. Or, if {@code this} stage completed exceptionally * and the supplied action throws an exception, then the returned - * stage completes exceptionally with this stage's exception. + * stage completes exceptionally with {@code this} stage's exception. * * @param action the action to perform * @return the new CompletionStage @@ -785,23 +799,23 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage with the same result or exception as - * this stage, that executes the given action using this stage's - * default asynchronous execution facility when this stage completes. + * {@code this} stage, that executes the given action using {@code this} stage's + * default asynchronous execution facility when {@code this} stage completes. * - *

    When this stage is complete, the given action is invoked with the + *

    When {@code this} stage is complete, the given action is invoked with the * result (or {@code null} if none) and the exception (or {@code null} - * if none) of this stage as arguments. The returned stage is completed + * if none) of {@code this} stage as arguments. The returned stage is completed * when the action returns. * *

    Unlike method {@link #handleAsync(BiFunction) handleAsync}, - * this method is not designed to translate completion outcomes, + * method {@code whenCompleteAsync} is not designed to translate completion outcomes, * so the supplied action should not throw an exception. However, - * if it does, the following rules apply: If this stage completed + * if it does, the following rules apply: If {@code this} stage completed * normally but the supplied action throws an exception, then the * returned stage completes exceptionally with the supplied - * action's exception. Or, if this stage completed exceptionally + * action's exception. Or, if {@code this} stage completed exceptionally * and the supplied action throws an exception, then the returned - * stage completes exceptionally with this stage's exception. + * stage completes exceptionally with {@code this} stage's exception. * * @param action the action to perform * @return the new CompletionStage @@ -811,23 +825,23 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a new CompletionStage with the same result or exception as - * this stage, that executes the given action using the supplied - * Executor when this stage completes. + * {@code this} stage, that executes the given action using the supplied + * Executor when {@code this} stage completes. * - *

    When this stage is complete, the given action is invoked with the + *

    When {@code this} stage is complete, the given action is invoked with the * result (or {@code null} if none) and the exception (or {@code null} - * if none) of this stage as arguments. The returned stage is completed + * if none) of {@code this} stage as arguments. The returned stage is completed * when the action returns. * *

    Unlike method {@link #handleAsync(BiFunction,Executor) handleAsync}, - * this method is not designed to translate completion outcomes, + * method {@code whenCompleteAsync} is not designed to translate completion outcomes, * so the supplied action should not throw an exception. However, - * if it does, the following rules apply: If this stage completed + * if it does, the following rules apply: If {@code this} stage completed * normally but the supplied action throws an exception, then the * returned stage completes exceptionally with the supplied - * action's exception. Or, if this stage completed exceptionally + * action's exception. Or, if {@code this} stage completed exceptionally * and the supplied action throws an exception, then the returned - * stage completes exceptionally with this stage's exception. + * stage completes exceptionally with {@code this} stage's exception. * * @param action the action to perform * @param executor the executor to use for asynchronous execution @@ -838,14 +852,14 @@ public CompletionStage runAfterEither(CompletionStage other, Executor executor); /** - * Returns a new CompletionStage that, when this stage completes - * exceptionally, is executed with this stage's exception as the - * argument to the supplied function. Otherwise, if this stage + * Returns a new CompletionStage that, when {@code this} stage completes + * exceptionally, is executed with {@code this} stage's exception as the + * argument to the supplied function. Otherwise, if {@code this} stage * completes normally, then the returned stage also completes * normally with the same value. * * @param fn the function to use to compute the value of the - * returned CompletionStage if this CompletionStage completed + * returned CompletionStage if {@code this} CompletionStage completed * exceptionally * @return the new CompletionStage */ @@ -853,10 +867,10 @@ public CompletionStage runAfterEither(CompletionStage other, (Function fn); /** - * Returns a new CompletionStage that, when this stage completes - * exceptionally, is executed with this stage's exception as the - * argument to the supplied function, using this stage's default - * asynchronous execution facility. Otherwise, if this stage + * Returns a new CompletionStage that, when {@code this} stage completes + * exceptionally, is executed with {@code this} stage's exception as the + * argument to the supplied function, using {@code this} stage's default + * asynchronous execution facility. Otherwise, if {@code this} stage * completes normally, then the returned stage also completes * normally with the same value. * @@ -865,7 +879,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the value of the - * returned CompletionStage if this CompletionStage completed + * returned CompletionStage if {@code this} CompletionStage completed * exceptionally * @return the new CompletionStage * @since 12 @@ -879,10 +893,10 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes - * exceptionally, is executed with this stage's exception as the + * Returns a new CompletionStage that, when {@code this} stage completes + * exceptionally, is executed with {@code this} stage's exception as the * argument to the supplied function, using the supplied Executor. - * Otherwise, if this stage completes normally, then the returned + * Otherwise, if {@code this} stage completes normally, then the returned * stage also completes normally with the same value. * * @implSpec The default implementation invokes {@link #handle}, @@ -890,7 +904,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the value of the - * returned CompletionStage if this CompletionStage completed + * returned CompletionStage if {@code this} CompletionStage completed * exceptionally * @param executor the executor to use for asynchronous execution * @return the new CompletionStage @@ -905,16 +919,16 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * exceptionally, is composed using the results of the supplied - * function applied to this stage's exception. + * function applied to {@code this} stage's exception. * * @implSpec The default implementation invokes {@link #handle}, * invoking the given function on exception, then {@link * #thenCompose} for result. * * @param fn the function to use to compute the returned - * CompletionStage if this CompletionStage completed exceptionally + * CompletionStage if {@code this} CompletionStage completed exceptionally * @return the new CompletionStage * @since 12 */ @@ -927,9 +941,9 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * exceptionally, is composed using the results of the supplied - * function applied to this stage's exception, using this stage's + * function applied to {@code this} stage's exception, using {@code this} stage's * default asynchronous execution facility. * * @implSpec The default implementation invokes {@link #handle}, @@ -937,7 +951,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the returned - * CompletionStage if this CompletionStage completed exceptionally + * CompletionStage if {@code this} CompletionStage completed exceptionally * @return the new CompletionStage * @since 12 */ @@ -951,9 +965,9 @@ public CompletionStage runAfterEither(CompletionStage other, } /** - * Returns a new CompletionStage that, when this stage completes + * Returns a new CompletionStage that, when {@code this} stage completes * exceptionally, is composed using the results of the supplied - * function applied to this stage's exception, using the + * function applied to {@code this} stage's exception, using the * supplied Executor. * * @implSpec The default implementation invokes {@link #handle}, @@ -961,7 +975,7 @@ public CompletionStage runAfterEither(CompletionStage other, * #thenCompose} for result. * * @param fn the function to use to compute the returned - * CompletionStage if this CompletionStage completed exceptionally + * CompletionStage if {@code this} CompletionStage completed exceptionally * @param executor the executor to use for asynchronous execution * @return the new CompletionStage * @since 12 @@ -978,9 +992,9 @@ public CompletionStage runAfterEither(CompletionStage other, /** * Returns a {@link CompletableFuture} maintaining the same - * completion properties as this stage. If this stage is already a - * CompletableFuture, this method may return this stage itself. - * Otherwise, invocation of this method may be equivalent in + * completion properties as {@code this} stage. If {@code this} stage is already a + * CompletableFuture, method {@code toCompletableFuture} may return {@code this} stage itself. + * Otherwise, invocation may be equivalent in * effect to {@code thenApply(x -> x)}, but returning an instance * of type {@code CompletableFuture}. * diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index 8734980cf80..b9df942fbfd 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -147,7 +147,7 @@ *

    Like {@link Hashtable} but unlike {@link HashMap}, this class * does not allow {@code null} to be used as a key or value. * - *

    ConcurrentHashMaps support a set of sequential and parallel bulk + *

    ConcurrentHashMaps support a set of sequential and parallel bulk * operations that, unlike most {@link Stream} methods, are designed * to be safely, and often sensibly, applied even with maps that are * being concurrently updated by other threads; for example, when @@ -3704,7 +3704,7 @@ final int batchFor(long b) { } /** - * Performs the given action for each (key, value). + * Performs the given {@linkplain ##Bulk bulk} action for each (key, value). * * @param parallelismThreshold the (estimated) number of elements * needed for this operation to be executed in parallel @@ -3720,7 +3720,7 @@ public void forEach(long parallelismThreshold, } /** - * Performs the given action for each non-null transformation + * Performs the given {@linkplain ##Bulk bulk} action for each non-null transformation * of each (key, value). * * @param parallelismThreshold the (estimated) number of elements @@ -3743,7 +3743,7 @@ public void forEach(long parallelismThreshold, } /** - * Returns a non-null result from applying the given search + * Returns a non-null result from applying the given {@linkplain ##Bulk bulk} search * function on each (key, value), or null if none. Upon * success, further element processing is suppressed and the * results of any other parallel invocations of the search @@ -3767,7 +3767,7 @@ public U search(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of accumulating the given {@linkplain ##Bulk bulk} transformation * of all (key, value) pairs using the given reducer to * combine values, or null if none. * @@ -3793,7 +3793,7 @@ public U reduce(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of accumulating the given {@linkplain ##Bulk bulk} transformation * of all (key, value) pairs using the given reducer to * combine values, and the given basis as an identity value. * @@ -3819,7 +3819,7 @@ public double reduceToDouble(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of accumulating the given {@linkplain ##Bulk bulk} transformation * of all (key, value) pairs using the given reducer to * combine values, and the given basis as an identity value. * @@ -3845,7 +3845,7 @@ public long reduceToLong(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of accumulating the given {@linkplain ##Bulk bulk} transformation * of all (key, value) pairs using the given reducer to * combine values, and the given basis as an identity value. * @@ -3871,7 +3871,7 @@ public int reduceToInt(long parallelismThreshold, } /** - * Performs the given action for each key. + * Performs the given {@linkplain ##Bulk bulk} action for each key. * * @param parallelismThreshold the (estimated) number of elements * needed for this operation to be executed in parallel @@ -3887,7 +3887,7 @@ public void forEachKey(long parallelismThreshold, } /** - * Performs the given action for each non-null transformation + * Performs the given {@linkplain ##Bulk bulk} action for each non-null transformation * of each key. * * @param parallelismThreshold the (estimated) number of elements @@ -3910,7 +3910,7 @@ public void forEachKey(long parallelismThreshold, } /** - * Returns a non-null result from applying the given search + * Returns a non-null result from applying the given {@linkplain ##Bulk bulk} search * function on each key, or null if none. Upon success, * further element processing is suppressed and the results of * any other parallel invocations of the search function are @@ -3934,7 +3934,7 @@ public U searchKeys(long parallelismThreshold, } /** - * Returns the result of accumulating all keys using the given + * Returns the result of {@linkplain ##Bulk bulk} accumulating all keys using the given * reducer to combine values, or null if none. * * @param parallelismThreshold the (estimated) number of elements @@ -3953,7 +3953,7 @@ public K reduceKeys(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all keys using the given reducer to combine values, or * null if none. * @@ -3979,7 +3979,7 @@ public U reduceKeys(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all keys using the given reducer to combine values, and * the given basis as an identity value. * @@ -4005,7 +4005,7 @@ public double reduceKeysToDouble(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all keys using the given reducer to combine values, and * the given basis as an identity value. * @@ -4031,7 +4031,7 @@ public long reduceKeysToLong(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all keys using the given reducer to combine values, and * the given basis as an identity value. * @@ -4057,7 +4057,7 @@ public int reduceKeysToInt(long parallelismThreshold, } /** - * Performs the given action for each value. + * Performs the given {@linkplain ##Bulk bulk} action for each value. * * @param parallelismThreshold the (estimated) number of elements * needed for this operation to be executed in parallel @@ -4074,7 +4074,7 @@ public void forEachValue(long parallelismThreshold, } /** - * Performs the given action for each non-null transformation + * Performs the given {@linkplain ##Bulk bulk} action for each non-null transformation * of each value. * * @param parallelismThreshold the (estimated) number of elements @@ -4097,7 +4097,7 @@ public void forEachValue(long parallelismThreshold, } /** - * Returns a non-null result from applying the given search + * Returns a non-null result from {@linkplain ##Bulk bulk} applying the given search * function on each value, or null if none. Upon success, * further element processing is suppressed and the results of * any other parallel invocations of the search function are @@ -4121,7 +4121,7 @@ public U searchValues(long parallelismThreshold, } /** - * Returns the result of accumulating all values using the + * Returns the result of {@linkplain ##Bulk bulk} accumulating all values using the * given reducer to combine values, or null if none. * * @param parallelismThreshold the (estimated) number of elements @@ -4139,7 +4139,7 @@ public V reduceValues(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all values using the given reducer to combine values, or * null if none. * @@ -4165,7 +4165,7 @@ public U reduceValues(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all values using the given reducer to combine values, * and the given basis as an identity value. * @@ -4191,7 +4191,7 @@ public double reduceValuesToDouble(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all values using the given reducer to combine values, * and the given basis as an identity value. * @@ -4217,7 +4217,7 @@ public long reduceValuesToLong(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all values using the given reducer to combine values, * and the given basis as an identity value. * @@ -4243,7 +4243,7 @@ public int reduceValuesToInt(long parallelismThreshold, } /** - * Performs the given action for each entry. + * Performs the given {@linkplain ##Bulk bulk} action for each entry. * * @param parallelismThreshold the (estimated) number of elements * needed for this operation to be executed in parallel @@ -4258,7 +4258,7 @@ public void forEachEntry(long parallelismThreshold, } /** - * Performs the given action for each non-null transformation + * Performs the given {@linkplain ##Bulk bulk} action for each non-null transformation * of each entry. * * @param parallelismThreshold the (estimated) number of elements @@ -4281,7 +4281,7 @@ public void forEachEntry(long parallelismThreshold, } /** - * Returns a non-null result from applying the given search + * Returns a non-null result from {@linkplain ##Bulk bulk} applying the given search * function on each entry, or null if none. Upon success, * further element processing is suppressed and the results of * any other parallel invocations of the search function are @@ -4305,7 +4305,7 @@ public U searchEntries(long parallelismThreshold, } /** - * Returns the result of accumulating all entries using the + * Returns the result of {@linkplain ##Bulk bulk} accumulating all entries using the * given reducer to combine values, or null if none. * * @param parallelismThreshold the (estimated) number of elements @@ -4323,7 +4323,7 @@ public Map.Entry reduceEntries(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all entries using the given reducer to combine values, * or null if none. * @@ -4349,7 +4349,7 @@ public U reduceEntries(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all entries using the given reducer to combine values, * and the given basis as an identity value. * @@ -4375,7 +4375,7 @@ public double reduceEntriesToDouble(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all entries using the given reducer to combine values, * and the given basis as an identity value. * @@ -4401,7 +4401,7 @@ public long reduceEntriesToLong(long parallelismThreshold, } /** - * Returns the result of accumulating the given transformation + * Returns the result of {@linkplain ##Bulk bulk} accumulating the given transformation * of all entries using the given reducer to combine values, * and the given basis as an identity value. * diff --git a/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java b/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java index 87e498d9c24..ca78c254624 100644 --- a/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java +++ b/src/java.base/share/classes/java/util/concurrent/CyclicBarrier.java @@ -44,7 +44,10 @@ * useful in programs involving a fixed sized party of threads that * must occasionally wait for each other. The barrier is called * cyclic because it can be re-used after the waiting threads - * are released. + * are released. If you need support for variable numbers of parties + * per cycle, alternate actions on exceptions, termination control, + * contention control, or status monitoring, use the more flexible + * {@link Phaser} class. * *

    A {@code CyclicBarrier} supports an optional {@link Runnable} command * that is run once per barrier point, after the last thread in the party diff --git a/src/java.base/share/classes/java/util/concurrent/ExecutorService.java b/src/java.base/share/classes/java/util/concurrent/ExecutorService.java index 0d4acf8913e..f899b56b288 100644 --- a/src/java.base/share/classes/java/util/concurrent/ExecutorService.java +++ b/src/java.base/share/classes/java/util/concurrent/ExecutorService.java @@ -56,7 +56,9 @@ * *

    Method {@code submit} extends base method {@link * Executor#execute(Runnable)} by creating and returning a {@link Future} - * that can be used to cancel execution and/or wait for completion. + * that can be used to cancel execution and/or wait for completion; + * also reporting exceptions that would otherwise be uncaught + * using method {@code execute}. * Methods {@code invokeAny} and {@code invokeAll} perform the most * commonly useful forms of bulk execution, executing a collection of * tasks and then waiting for at least one, or all, to diff --git a/src/java.base/share/classes/java/util/concurrent/Executors.java b/src/java.base/share/classes/java/util/concurrent/Executors.java index ba7c2e1efee..ef3d6348010 100644 --- a/src/java.base/share/classes/java/util/concurrent/Executors.java +++ b/src/java.base/share/classes/java/util/concurrent/Executors.java @@ -306,7 +306,7 @@ public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFa } /** - * Creates a thread pool that can schedule commands to run after a + * Creates a fixed-size thread pool that can schedule commands to run after a * given delay, or to execute periodically. * @param corePoolSize the number of threads to keep in the pool, * even if they are idle @@ -318,7 +318,7 @@ public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) } /** - * Creates a thread pool that can schedule commands to run after a + * Creates a fixed-size thread pool that can schedule commands to run after a * given delay, or to execute periodically. * @param corePoolSize the number of threads to keep in the pool, * even if they are idle diff --git a/src/java.base/share/classes/java/util/concurrent/Flow.java b/src/java.base/share/classes/java/util/concurrent/Flow.java index 1aefaea43b0..16b2ba5e9d8 100644 --- a/src/java.base/share/classes/java/util/concurrent/Flow.java +++ b/src/java.base/share/classes/java/util/concurrent/Flow.java @@ -60,7 +60,8 @@ * TRUE} item to a single subscriber. Because the subscriber receives * only a single item, this class does not use buffering and ordering * control required in most implementations (for example {@link - * SubmissionPublisher}). + * SubmissionPublisher}), and omits some error processing needed to + * fully conform to the Reactive Streams specification. * *

     {@code
      * class OneShotPublisher implements Publisher {
    diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
    index a7821921bc9..482fe3cf801 100644
    --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
    +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java
    @@ -140,7 +140,7 @@
      * tasks, as well as method {@link #submitWithTimeout} to cancel tasks
      * that take too long. The scheduled functions or actions may create
      * and invoke other {@linkplain ForkJoinTask ForkJoinTasks}. Delayed
    - * actions become enabled and behave as ordinary submitted
    + * actions become enabled for execution and behave as ordinary submitted
      * tasks when their delays elapse.  Scheduling methods return
      * {@linkplain ForkJoinTask ForkJoinTasks} that implement the {@link
      * ScheduledFuture} interface. Resource exhaustion encountered after
    @@ -153,7 +153,7 @@
      * to disable all delayed tasks upon shutdown, and method {@link
      * #shutdownNow} may be used to instead unconditionally initiate pool
      * termination. Monitoring methods such as {@link #getQueuedTaskCount}
    - * do not include scheduled tasks that are not yet enabled to execute,
    + * do not include scheduled tasks that are not yet enabled for execution,
      * which are reported separately by method {@link
      * #getDelayedTaskCount}.
      *
    @@ -3505,7 +3505,7 @@ final  ScheduledForkJoinTask scheduleDelayedTask(ScheduledForkJoinTask
         }
     
         /**
    -     * Submits a one-shot task that becomes enabled after the given
    +     * Submits a one-shot task that becomes enabled for execution after the given
          * delay.  At that point it will execute unless explicitly
          * cancelled, or fail to execute (eventually reporting
          * cancellation) when encountering resource exhaustion, or the
    @@ -3533,7 +3533,7 @@ public ScheduledFuture schedule(Runnable command,
         }
     
         /**
    -     * Submits a value-returning one-shot task that becomes enabled
    +     * Submits a value-returning one-shot task that becomes enabled for execution
          * after the given delay. At that point it will execute unless
          * explicitly cancelled, or fail to execute (eventually reporting
          * cancellation) when encountering resource exhaustion, or the
    @@ -3562,7 +3562,7 @@ public  ScheduledFuture schedule(Callable callable,
         }
     
         /**
    -     * Submits a periodic action that becomes enabled first after the
    +     * Submits a periodic action that becomes enabled for execution first after the
          * given initial delay, and subsequently with the given period;
          * that is, executions will commence after
          * {@code initialDelay}, then {@code initialDelay + period}, then
    @@ -3616,7 +3616,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable command,
         }
     
         /**
    -     * Submits a periodic action that becomes enabled first after the
    +     * Submits a periodic action that becomes enabled for execution first after the
          * given initial delay, and subsequently with the given delay
          * between the termination of one execution and the commencement of
          * the next.
    diff --git a/src/java.base/share/classes/java/util/concurrent/Future.java b/src/java.base/share/classes/java/util/concurrent/Future.java
    index c6f3036c2d2..2ac837d7270 100644
    --- a/src/java.base/share/classes/java/util/concurrent/Future.java
    +++ b/src/java.base/share/classes/java/util/concurrent/Future.java
    @@ -50,6 +50,26 @@
      * declare types of the form {@code Future} and
      * return {@code null} as a result of the underlying task.
      *
    + * 

    Cancellation of a Future need not abruptly terminate its + * computation. Method {@code cancel} causes {@code isCancelled()} to + * return {@code true} unless already {@code isDone()}; in either case + * {@code isDone()} subsequently reports {@code true}. This suppresses + * execution by an {@link ExecutorService} if not already started. + * There are several options for suppressing unnecessary computation + * or unblocking a running Future that will not generate a + * result. When task bodies are simple and short, no special attention + * is warranted. Computational methods in Future-aware code bodies + * (for example {@link ForkJoinTask}, {@link FutureTask}) may inspect + * their own {@code isDone()} status before or while engaging in + * expensive computations. In blocking I/O or communication contexts, + * the optional {@code mayInterruptIfRunning} argument of {@code + * cancel} may be used to support conventions that tasks should + * unblock and exit when {@link Thread#interrupted}, whether checked + * inside a task body or as a response to an {@link + * InterruptedException}. It is still preferable to additionally + * check {@code isDone()} status when possible to avoid unintended + * effects of other uses of {@link Thread#interrupt}. + * *

    Sample Usage (Note that the following classes are all * made-up.) * diff --git a/src/java.base/share/classes/java/util/concurrent/FutureTask.java b/src/java.base/share/classes/java/util/concurrent/FutureTask.java index b905e71aeef..2ec97629105 100644 --- a/src/java.base/share/classes/java/util/concurrent/FutureTask.java +++ b/src/java.base/share/classes/java/util/concurrent/FutureTask.java @@ -285,7 +285,9 @@ protected void done() { } * this future has already been set or has been cancelled. * *

    This method is invoked internally by the {@link #run} method - * upon successful completion of the computation. + * upon successful completion of the computation. Invocation in + * other contexts has undefined effects. Any override of this + * method in subclasses should include {@code super.set(v)}. * * @param v the value */ diff --git a/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java b/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java index b6b088ae7cd..8585cfe1082 100644 --- a/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java +++ b/src/java.base/share/classes/java/util/concurrent/RunnableFuture.java @@ -47,8 +47,9 @@ */ public interface RunnableFuture extends Runnable, Future { /** - * Sets this Future to the result of its computation - * unless it has been cancelled. + * Sets this Future to the result of its computation unless it has + * been cancelled (or has already been invoked, in which case + * effects are undefined). */ void run(); } diff --git a/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java index 4d63ffae4bb..034d98687c2 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledExecutorService.java @@ -40,10 +40,12 @@ * delay, or to execute periodically. * *

    The {@code schedule} methods create tasks with various delays - * and return a task object that can be used to cancel or check - * execution. The {@code scheduleAtFixedRate} and - * {@code scheduleWithFixedDelay} methods create and execute tasks - * that run periodically until cancelled. + * and return {@link ScheduledFuture} objects that can be used to cancel or check + * execution. When delays elapse, tasks are enabled for execution and + * behave in accord with other {@link ExecutorService} tasks, except + * that {@code scheduleAtFixedRate} and {@code scheduleWithFixedDelay} + * methods create and execute tasks that run periodically until + * cancelled. * *

    Commands submitted using the {@link Executor#execute(Runnable)} * and {@link ExecutorService} {@code submit} methods are scheduled @@ -91,7 +93,7 @@ public interface ScheduledExecutorService extends ExecutorService { /** - * Submits a one-shot task that becomes enabled after the given delay. + * Submits a one-shot task that becomes enabled for execution after the given delay. * * @param command the task to execute * @param delay the time from now to delay execution @@ -107,7 +109,7 @@ public ScheduledFuture schedule(Runnable command, long delay, TimeUnit unit); /** - * Submits a value-returning one-shot task that becomes enabled + * Submits a value-returning one-shot task that becomes enabled for execution * after the given delay. * * @param callable the function to execute @@ -123,7 +125,7 @@ public ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit); /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given period; * that is, executions will commence after * {@code initialDelay}, then {@code initialDelay + period}, then @@ -167,7 +169,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable command, TimeUnit unit); /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given delay * between the termination of one execution and the commencement of * the next. diff --git a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java index 94f40ccf6f5..23398aeae28 100644 --- a/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java +++ b/src/java.base/share/classes/java/util/concurrent/ScheduledThreadPoolExecutor.java @@ -57,7 +57,7 @@ * capabilities of {@link ThreadPoolExecutor} (which this class * extends) are required. * - *

    Delayed tasks execute no sooner than they are enabled, but + *

    Delayed tasks execute no sooner than they are enabled for execution, but * without any real-time guarantees about when, after they are * enabled, they will commence. Tasks scheduled for exactly the same * execution time are enabled in first-in-first-out (FIFO) order of @@ -568,7 +568,7 @@ public ScheduledFuture schedule(Callable callable, } /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given period; * that is, executions will commence after * {@code initialDelay}, then {@code initialDelay + period}, then @@ -621,7 +621,7 @@ public ScheduledFuture scheduleAtFixedRate(Runnable command, } /** - * Submits a periodic action that becomes enabled first after the + * Submits a periodic action that becomes enabled for execution first after the * given initial delay, and subsequently with the given delay * between the termination of one execution and the commencement of * the next. diff --git a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java index 3a8f3746637..f793d2bcabd 100644 --- a/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java +++ b/src/java.base/share/classes/java/util/concurrent/SubmissionPublisher.java @@ -162,8 +162,8 @@ * (this.subscription = subscription).request(1); * } * public void onNext(S item) { - * subscription.request(1); * submit(function.apply(item)); + * subscription.request(1); * } * public void onError(Throwable ex) { closeExceptionally(ex); } * public void onComplete() { close(); } @@ -602,9 +602,11 @@ public int offer(T item, long timeout, TimeUnit unit, /** * Unless already closed, issues {@link * Flow.Subscriber#onComplete() onComplete} signals to current - * subscribers, and disallows subsequent attempts to publish. - * Upon return, this method does NOT guarantee that all - * subscribers have yet completed. + * subscribers, and disallows subsequent attempts to publish. To + * ensure uniform ordering among subscribers, this method may + * await completion of in-progress offers. Upon return, this + * method does NOT guarantee that all subscribers have + * yet completed. */ public void close() { ReentrantLock lock = this.lock; diff --git a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java index f02aa9f5931..d116fb9b22b 100644 --- a/src/java.base/share/classes/java/util/concurrent/TimeUnit.java +++ b/src/java.base/share/classes/java/util/concurrent/TimeUnit.java @@ -398,6 +398,8 @@ else if (s == MICRO_SCALE) * @param obj the object to wait on * @param timeout the maximum time to wait. If less than * or equal to zero, do not wait at all. + * @throws IllegalMonitorStateException if the current thread is not + * the owner of the object's monitor. * @throws InterruptedException if interrupted while waiting */ public void timedWait(Object obj, long timeout) diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java index e01b3ec7d50..f947eb4f7db 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicIntegerFieldUpdater.java @@ -46,10 +46,11 @@ /** * A reflection-based utility that enables atomic updates to - * designated {@code volatile int} fields of designated classes. - * This class is designed for use in atomic data structures in which - * several fields of the same node are independently subject to atomic - * updates. + * designated non-static {@code volatile int} fields of designated + * classes, providing a subset of the functionality of class {@link + * VarHandle} that should be used instead. This class is designed for + * use in atomic data structures in which several fields of the same + * node are independently subject to atomic updates. * *

    Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java index 57722f33371..b31a8edf53a 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicLongFieldUpdater.java @@ -46,10 +46,11 @@ /** * A reflection-based utility that enables atomic updates to - * designated {@code volatile long} fields of designated classes. - * This class is designed for use in atomic data structures in which - * several fields of the same node are independently subject to atomic - * updates. + * designated non-static {@code volatile long} fields of designated + * classes, providing a subset of the functionality of class {@link + * VarHandle} that should be used instead. This class is designed for + * use in atomic data structures in which several fields of the same + * node are independently subject to atomic updates. * *

    Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. diff --git a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java index 1c0c6d0afd0..e3ca4830d5a 100644 --- a/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java +++ b/src/java.base/share/classes/java/util/concurrent/atomic/AtomicReferenceFieldUpdater.java @@ -46,11 +46,12 @@ /** * A reflection-based utility that enables atomic updates to - * designated {@code volatile} reference fields of designated - * classes. This class is designed for use in atomic data structures - * in which several reference fields of the same node are - * independently subject to atomic updates. For example, a tree node - * might be declared as + * designated non-static {@code volatile} reference fields of + * designated classes, providing a subset of the functionality of + * class {@link VarHandle} that should be used instead. This class + * may be used in atomic data structures in which several reference + * fields of the same node are independently subject to atomic + * updates. For example, a tree node might be declared as * *

     {@code
      * class Node {
    @@ -68,6 +69,26 @@
      *   // ... and so on
      * }}
    * + * However, it is preferable to use {@link VarHandle}: + *
     {@code
    + * import java.lang.invoke.VarHandle;
    + * import java.lang.invoke.MethodHandles;
    + * class Node {
    + *  private volatile Node left, right;
    + *  private static final VarHandle LEFT, RIGHT;
    + *  Node getLeft() { return left; }
    + *  boolean compareAndSetLeft(Node expect, Node update) {
    + *    return LEFT.compareAndSet(this, expect, update);
    + *  }
    + *  // ... and so on
    + *  static { try {
    + *    MethodHandles.Lookup l = MethodHandles.lookup();
    + *    LEFT  = l.findVarHandle(Node.class, "left", Node.class);
    + *    RIGHT = l.findVarHandle(Node.class, "right", Node.class);
    + *   } catch (ReflectiveOperationException e) {
    + *     throw new ExceptionInInitializerError(e);
    + * }}}}
    + * *

    Note that the guarantees of the {@code compareAndSet} * method in this class are weaker than in other atomic classes. * Because this class cannot ensure that all uses of the field diff --git a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java index 3e0b293380f..536996fd273 100644 --- a/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java +++ b/src/java.base/share/classes/java/util/concurrent/locks/ReentrantReadWriteLock.java @@ -97,6 +97,10 @@ * perform reads under read locks. If a reader tries to acquire the * write lock it will never succeed. * + *

    Note: If you do not rely on reentrancy, you may find that {@link + * StampedLock} offers better performance, as in: {@code ReadWriteLock + * lock = new StampedLock().asReadWriteLock()}. + * *

  • Lock downgrading *

    Reentrancy also allows downgrading from the write lock to a read lock, * by acquiring the write lock, then the read lock and then releasing the @@ -734,11 +738,13 @@ protected ReadLock(ReentrantReadWriteLock lock) { * Acquires the read lock. * *

    Acquires the read lock if the write lock is not held by - * another thread and returns immediately. + * any thread and returns immediately. * - *

    If the write lock is held by another thread then - * the current thread becomes disabled for thread scheduling - * purposes and lies dormant until the read lock has been acquired. + *

    If the write lock is held by any thread or the fairness + * policy prohibits acquisition of the read lock at this time, + * then the current thread becomes disabled for thread + * scheduling purposes and lies dormant until the read lock + * has been acquired. */ public void lock() { sync.acquireShared(1); @@ -749,11 +755,13 @@ public void lock() { * {@linkplain Thread#interrupt interrupted}. * *

    Acquires the read lock if the write lock is not held - * by another thread and returns immediately. + * by any thread and returns immediately. * - *

    If the write lock is held by another thread then the - * current thread becomes disabled for thread scheduling - * purposes and lies dormant until one of two things happens: + *

    If the write lock is held by any thread or the fairness + * policy prohibits acquisition of the read lock at this time, + * then the current thread becomes disabled for thread + * scheduling purposes and lies dormant until one of two + * things happens: * *

      * @@ -794,7 +802,7 @@ public void lockInterruptibly() throws InterruptedException { * another thread at the time of invocation. * *

      Acquires the read lock if the write lock is not held by - * another thread and returns immediately with the value + * any thread and returns immediately with the value * {@code true}. Even when this lock has been set to use a * fair ordering policy, a call to {@code tryLock()} * will immediately acquire the read lock if it is @@ -806,7 +814,7 @@ public void lockInterruptibly() throws InterruptedException { * tryLock(0, TimeUnit.SECONDS)} which is almost equivalent * (it also detects interruption). * - *

      If the write lock is held by another thread then + *

      If the write lock is held by any thread then * this method will return immediately with the value * {@code false}. * diff --git a/src/java.base/share/classes/java/util/concurrent/package-info.java b/src/java.base/share/classes/java/util/concurrent/package-info.java index dd0c8f79bc0..f237017799d 100644 --- a/src/java.base/share/classes/java/util/concurrent/package-info.java +++ b/src/java.base/share/classes/java/util/concurrent/package-info.java @@ -222,7 +222,9 @@ *

    • they are guaranteed to traverse elements as they existed upon * construction exactly once, and may (but are not guaranteed to) * reflect any modifications subsequent to construction. - *
    + *
  • These properties extend to other iteration-based + * operations. In particular, {@link Object#equals} is almost never + * useful unless both collections are known to be quiescent. * *

    Memory Consistency Properties

    * From 8df6b2c4a355751cd8ca37cc5932be66bccaa123 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Thu, 26 Jun 2025 13:37:13 +0000 Subject: [PATCH 189/213] 8359830: Incorrect os.version reported on macOS Tahoe 26 (Beta) Reviewed-by: rriggs, lancea, kcr --- .../macosx/native/libjava/java_props_macosx.c | 52 ++++++++++++------ test/jdk/java/lang/System/OsVersionTest.java | 54 +++++++++++-------- 2 files changed, 67 insertions(+), 39 deletions(-) diff --git a/src/java.base/macosx/native/libjava/java_props_macosx.c b/src/java.base/macosx/native/libjava/java_props_macosx.c index 07bc2be9d54..6656bf04efc 100644 --- a/src/java.base/macosx/native/libjava/java_props_macosx.c +++ b/src/java.base/macosx/native/libjava/java_props_macosx.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ * questions. */ +#include #include #include #include @@ -229,33 +230,50 @@ void setOSNameAndVersion(java_props_t *sprops) { NSString *nsVerStr = NULL; char* osVersionCStr = NULL; NSOperatingSystemVersion osVer = [[NSProcessInfo processInfo] operatingSystemVersion]; - // Copy out the char* if running on version other than 10.16 Mac OS (10.16 == 11.x) - // or explicitly requesting version compatibility - if (!((long)osVer.majorVersion == 10 && (long)osVer.minorVersion >= 16) || - (getenv("SYSTEM_VERSION_COMPAT") != NULL)) { - if (osVer.patchVersion == 0) { // Omit trailing ".0" + // Some macOS versions require special handling. For example, + // when the NSOperatingSystemVersion reports 10.16 as the version + // then it should be treated as 11. Similarly, when it reports 16.0 + // as the version then it should be treated as 26. + // If the SYSTEM_VERSION_COMPAT environment variable (a macOS construct) + // is set to 1, then we don't do any special handling for any versions + // and just literally use the value that NSOperatingSystemVersion reports. + const char* envVal = getenv("SYSTEM_VERSION_COMPAT"); + const bool versionCompatEnabled = envVal != NULL + && strncmp(envVal, "1", 1) == 0; + const bool requiresSpecialHandling = + ((long) osVer.majorVersion == 10 && (long) osVer.minorVersion >= 16) + || ((long) osVer.majorVersion == 16 && (long) osVer.minorVersion >= 0); + if (!requiresSpecialHandling || versionCompatEnabled) { + // no special handling - just use the version reported + // by NSOperatingSystemVersion + if (osVer.patchVersion == 0) { + // Omit trailing ".0" nsVerStr = [NSString stringWithFormat:@"%ld.%ld", (long)osVer.majorVersion, (long)osVer.minorVersion]; } else { nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld", - (long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion]; + (long)osVer.majorVersion, (long)osVer.minorVersion, + (long)osVer.patchVersion]; } } else { - // Version 10.16, without explicit env setting of SYSTEM_VERSION_COMPAT - // AKA 11+ Read the *real* ProductVersion from the hidden link to avoid SYSTEM_VERSION_COMPAT - // If not found, fallback below to the SystemVersion.plist - NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile : - @"/System/Library/CoreServices/.SystemVersionPlatform.plist"]; + // Requires special handling. We ignore the version reported + // by the NSOperatingSystemVersion API and instead read the + // *real* ProductVersion from + // /System/Library/CoreServices/.SystemVersionPlatform.plist. + // If not found there, then as a last resort we fallback to + // /System/Library/CoreServices/SystemVersion.plist + NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/.SystemVersionPlatform.plist"]; if (version != NULL) { - nsVerStr = [version objectForKey : @"ProductVersion"]; + nsVerStr = [version objectForKey: @"ProductVersion"]; } } - // Fallback to reading the SystemVersion.plist + // Last resort - fallback to reading the SystemVersion.plist if (nsVerStr == NULL) { - NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile : - @"/System/Library/CoreServices/SystemVersion.plist"]; + NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile: + @"/System/Library/CoreServices/SystemVersion.plist"]; if (version != NULL) { - nsVerStr = [version objectForKey : @"ProductVersion"]; + nsVerStr = [version objectForKey: @"ProductVersion"]; } } diff --git a/test/jdk/java/lang/System/OsVersionTest.java b/test/jdk/java/lang/System/OsVersionTest.java index d35f71453b1..9a1cb976db8 100644 --- a/test/jdk/java/lang/System/OsVersionTest.java +++ b/test/jdk/java/lang/System/OsVersionTest.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2015, 2021 SAP SE. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,56 +29,65 @@ /* * @test - * @bug 8132374 + * @bug 8132374 8359830 * @summary Check that the value of the os.version property is equal * to the value of the corresponding OS provided tools. * @library /test/lib + * @build jtreg.SkippedException * @run main OsVersionTest * @author Volker Simonis */ public class OsVersionTest { - public static void main(String args[]) throws Throwable { + public static void main(String[] args) throws Throwable { final String osVersion = System.getProperty("os.version"); if (osVersion == null) { - throw new Error("Cant query 'os.version' property!"); + throw new Error("Missing value for os.version system property"); } if (Platform.isLinux()) { OutputAnalyzer output = ProcessTools.executeProcess("uname", "-r"); + output.shouldHaveExitValue(0); if (!osVersion.equals(output.getOutput().trim())) { throw new Error(osVersion + " != " + output.getOutput().trim()); } - } - else if (Platform.isOSX()) { - OutputAnalyzer output = ProcessTools.executeProcess("sw_vers", "-productVersion"); - String swVersOutput = output.getOutput().trim(); - if (!osVersion.equals(swVersOutput)) { - // This section can be removed if minimum build SDK is xcode 12+ - if (swVersOutput.startsWith(osVersion)) { - throw new SkippedException("MacOS version only matches in parts, this is expected when " + - "JDK was built with Xcode < 12 and MacOS version patch is > 0"); - } - throw new Error(osVersion + " != " + swVersOutput); - } - } - else if (Platform.isAix()) { + } else if (Platform.isOSX()) { + testMacOS(osVersion); + } else if (Platform.isAix()) { OutputAnalyzer output1 = ProcessTools.executeProcess("uname", "-v"); + output1.shouldHaveExitValue(0); OutputAnalyzer output2 = ProcessTools.executeProcess("uname", "-r"); + output2.shouldHaveExitValue(0); String version = output1.getOutput().trim() + "." + output2.getOutput().trim(); if (!osVersion.equals(version)) { throw new Error(osVersion + " != " + version); } - } - else if (Platform.isWindows()) { + } else if (Platform.isWindows()) { OutputAnalyzer output = ProcessTools.executeProcess("cmd", "/c", "ver"); + output.shouldHaveExitValue(0); String version = output.firstMatch(".+\\[Version ([0-9.]+)\\]", 1); if (version == null || !version.startsWith(osVersion)) { throw new Error(osVersion + " != " + version); } - } - else { - System.out.println("This test is currently not supported on " + + } else { + throw new jtreg.SkippedException("This test is currently not supported on " + Platform.getOsName()); } } + + private static void testMacOS(final String sysPropOsVersion) throws Exception { + final ProcessBuilder pb = new ProcessBuilder("sw_vers", "-productVersion"); + // if the test was launched with SYSTEM_VERSION_COMPAT environment variable set, + // then propagate that to the sw_vers too + final String versionCompat = System.getenv().get("SYSTEM_VERSION_COMPAT"); + if (versionCompat != null) { + pb.environment().put("SYSTEM_VERSION_COMPAT", versionCompat); + } + final OutputAnalyzer output = ProcessTools.executeCommand(pb); + output.shouldHaveExitValue(0); + final String swVersOutput = output.getOutput().trim(); + if (!sysPropOsVersion.equals(swVersOutput)) { + throw new Error("sw_vers reports macOS version: " + swVersOutput + + " but os.version system property reports version: " + sysPropOsVersion); + } + } } From 7576064a10c0f7a1fbfe88fc39254f32005d88f8 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Thu, 26 Jun 2025 14:09:27 +0000 Subject: [PATCH 190/213] 8359061: Update and ProblemList manual test java/awt/Cursor/CursorDragTest/ListDragCursor.java Reviewed-by: honkar, aivanov --- test/jdk/ProblemList.txt | 1 + .../Cursor/CursorDragTest/ListDragCursor.java | 100 ++++++++++++++---- 2 files changed, 82 insertions(+), 19 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index ed709e1b7cc..382ce443813 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -832,6 +832,7 @@ java/awt/Checkbox/CheckboxNullLabelTest.java 8340870 windows-all java/awt/dnd/WinMoveFileToShellTest.java 8341665 windows-all java/awt/Menu/MenuVisibilityTest.java 8161110 macosx-all java/awt/Modal/NativeDialogToFrontBackTest.java 7188049 windows-all,linux-all +java/awt/Cursor/CursorDragTest/ListDragCursor.java 7177297 macosx-all ############################################################################ diff --git a/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java b/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java index 32923f1d78b..da0394a1392 100644 --- a/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java +++ b/test/jdk/java/awt/Cursor/CursorDragTest/ListDragCursor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,42 +25,60 @@ * @test * @bug 4313052 * @summary Test cursor changes after mouse dragging ends - * @library /java/awt/regtesthelpers - * @build PassFailJFrame * @run main/manual ListDragCursor */ +import java.awt.BorderLayout; +import java.awt.Button; import java.awt.Cursor; +import java.awt.EventQueue; import java.awt.Frame; import java.awt.List; import java.awt.Panel; import java.awt.TextArea; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; public class ListDragCursor { - public static void main(String[] args) throws Exception { - String INSTRUCTIONS = """ + private static final String INSTRUCTIONS = """ 1. Move mouse to the TextArea. 2. Press the left mouse button. 3. Drag mouse to the list. 4. Release the left mouse button. - If the mouse cursor starts as a Text Line Cursor and changes - to a regular Pointer Cursor, then Hand Cursor when hovering - the list, pass the test. This test fails if the cursor does - not update at all when pointing over the different components. + The mouse cursor should appear as an I-beam cursor + and should stay the same while dragging across the + components. Once you reach the list, release the + left mouse button. As soon as you release the left + mouse button, the cursor should change to a Hand + cursor. If true, this test passes. + + The test fails if the cursor updates while dragging + over the components before releasing the left + mouse button. """; - PassFailJFrame.builder() - .title("Test Instructions") - .instructions(INSTRUCTIONS) - .rows((int) INSTRUCTIONS.lines().count() + 2) - .columns(35) - .testUI(ListDragCursor::createUI) - .build() - .awaitAndCheck(); + private static Frame testFrame; + private static Frame instructionsFrame; + + private static final CountDownLatch countDownLatch = new CountDownLatch(1); + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> { + instructionsFrame = createInstructionsFrame(); + testFrame = createTestFrame(); + }); + if (!countDownLatch.await(5, TimeUnit.MINUTES)) { + throw new RuntimeException("Test timeout : No action was" + + " taken on the test."); + } + } finally { + EventQueue.invokeAndWait(ListDragCursor::disposeFrames); + } } - public static Frame createUI() { + static Frame createTestFrame() { Frame frame = new Frame("Cursor change after drag"); Panel panel = new Panel(); @@ -78,7 +96,51 @@ public static Frame createUI() { panel.add(list); frame.add(panel); - frame.setBounds(300, 100, 300, 150); + frame.setSize(300, 150); + frame.setLocation(instructionsFrame.getX() + + instructionsFrame.getWidth(), + instructionsFrame.getY()); + frame.setVisible(true); + return frame; + } + + static Frame createInstructionsFrame() { + Frame frame = new Frame("Test Instructions"); + Panel mainPanel = new Panel(new BorderLayout()); + TextArea textArea = new TextArea(INSTRUCTIONS, + 15, 35, TextArea.SCROLLBARS_NONE); + + Panel btnPanel = new Panel(); + Button passBtn = new Button("Pass"); + Button failBtn = new Button("Fail"); + btnPanel.add(passBtn); + btnPanel.add(failBtn); + + passBtn.addActionListener(e -> { + countDownLatch.countDown(); + System.out.println("Test passed."); + }); + failBtn.addActionListener(e -> { + countDownLatch.countDown(); + throw new RuntimeException("Test Failed."); + }); + + mainPanel.add(textArea, BorderLayout.CENTER); + mainPanel.add(btnPanel, BorderLayout.SOUTH); + + frame.add(mainPanel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); return frame; } + + static void disposeFrames() { + if (testFrame != null) { + testFrame.dispose(); + } + if (instructionsFrame != null) { + instructionsFrame.dispose(); + } + } } From a0c3efa6a80fe95e22faf5a732e42f1e1291fb4c Mon Sep 17 00:00:00 2001 From: Kelvin Nilsen Date: Thu, 26 Jun 2025 14:36:33 +0000 Subject: [PATCH 191/213] 8359947: GenShen: use smaller TLABs by default Reviewed-by: phh, xpeng --- src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp | 7 ++++++- src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp | 4 +++- .../gc/shenandoah/generational/TestOldGrowthTriggers.java | 8 ++++---- 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp index d635781f90f..df2cd18042f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahArguments.cpp @@ -184,9 +184,10 @@ void ShenandoahArguments::initialize() { // Current default is good for generational collectors that run frequent young GCs. // With Shenandoah, GC cycles are much less frequent, so we need we need sizing policy // to converge faster over smaller number of resizing decisions. - if (FLAG_IS_DEFAULT(TLABAllocationWeight)) { + if (strcmp(ShenandoahGCMode, "generational") && FLAG_IS_DEFAULT(TLABAllocationWeight)) { FLAG_SET_DEFAULT(TLABAllocationWeight, 90); } + // In generational mode, let TLABAllocationWeight keeps its default value of 35. if (GCCardSizeInBytes < ShenandoahMinCardSizeInBytes) { vm_exit_during_initialization( @@ -217,6 +218,10 @@ void ShenandoahArguments::initialize_alignments() { } SpaceAlignment = align; HeapAlignment = align; + + if (FLAG_IS_DEFAULT(TLABSize)) { + TLABSize = MAX2(ShenandoahHeapRegion::region_size_bytes() / 256, (size_t) 32 * 1024); + } } CollectedHeap* ShenandoahArguments::create_heap() { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index d00a99ee728..05eb0c299a5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -790,8 +790,10 @@ size_t ShenandoahHeapRegion::setup_sizes(size_t max_heap_size) { RegionCount = align_up(max_heap_size, RegionSizeBytes) / RegionSizeBytes; guarantee(RegionCount >= MIN_NUM_REGIONS, "Should have at least minimum regions"); + // Limit TLAB size for better startup behavior and more equitable distribution of memory between contending mutator threads. guarantee(MaxTLABSizeWords == 0, "we should only set it once"); - MaxTLABSizeWords = align_down(RegionSizeWords, MinObjAlignment); + MaxTLABSizeWords = align_down(MIN2(RegionSizeWords, MAX2(RegionSizeWords / 32, (size_t) (256 * 1024) / HeapWordSize)), + MinObjAlignment); guarantee(MaxTLABSizeBytes == 0, "we should only set it once"); MaxTLABSizeBytes = MaxTLABSizeWords * HeapWordSize; diff --git a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java index 840ceffc4fe..b5d191e33ba 100644 --- a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java +++ b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java @@ -57,17 +57,17 @@ public static void makeOldAllocations() { for (int i = 0; i < ArraySize; i++) { int replaceIndex = r.nextInt(ArraySize); int deriveIndex = r.nextInt(ArraySize); - switch (i & 0x3) { - case 0: + switch (i & 0x7) { + case 0,1,2: // creates new old BigInteger, releases old BigInteger, // may create ephemeral data while computing gcd array[replaceIndex] = array[replaceIndex].gcd(array[deriveIndex]); break; - case 1: + case 3,4: // creates new old BigInteger, releases old BigInteger array[replaceIndex] = array[replaceIndex].multiply(array[deriveIndex]); break; - case 2,3: + case 5,6,7: // do nothing, let all objects in the array age to increase pressure on old generation break; } From bd666f90eb7325c5a8c51cb2b9c28e177c5fe3a3 Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Thu, 26 Jun 2025 15:01:56 +0000 Subject: [PATCH 192/213] 8360522: G1: Flag constraint functions for G1SATBBufferSize and G1UpdateBufferSize are skipped during argument validation Reviewed-by: tschatzl, ayang --- src/hotspot/share/gc/g1/g1_globals.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1_globals.hpp b/src/hotspot/share/gc/g1/g1_globals.hpp index 44d0d22257e..7ca2e997676 100644 --- a/src/hotspot/share/gc/g1/g1_globals.hpp +++ b/src/hotspot/share/gc/g1/g1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,7 +144,7 @@ \ product(size_t, G1SATBBufferSize, 1*K, \ "Number of entries in an SATB log buffer.") \ - constraint(G1SATBBufferSizeConstraintFunc, AtParse) \ + constraint(G1SATBBufferSizeConstraintFunc, AfterErgo) \ \ develop(uintx, G1SATBProcessCompletedThreshold, 20, \ "Number of completed buffers that triggers log processing.") \ @@ -163,7 +163,7 @@ \ product(size_t, G1UpdateBufferSize, 256, \ "Size of an update buffer") \ - constraint(G1UpdateBufferSizeConstraintFunc, AtParse) \ + constraint(G1UpdateBufferSizeConstraintFunc, AfterErgo) \ \ product(uint, G1RSetUpdatingPauseTimePercent, 10, \ "A target percentage of time that is allowed to be spend on " \ From 7f702cf483018155a22a32736da8d80a11c9eca9 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Thu, 26 Jun 2025 15:12:35 +0000 Subject: [PATCH 193/213] 8360458: Rename Deferred<> to DeferredStatic<> and improve usage description Reviewed-by: jsikstro, jsjolen, stefank --- src/hotspot/share/nmt/memTracker.cpp | 4 +- src/hotspot/share/nmt/memTracker.hpp | 4 +- src/hotspot/share/nmt/memoryFileTracker.cpp | 2 +- src/hotspot/share/nmt/memoryFileTracker.hpp | 4 +- .../{deferred.hpp => deferredStatic.hpp} | 47 ++++--- .../gtest/utilities/test_deferredStatic.cpp | 120 ++++++++++++++++++ 6 files changed, 150 insertions(+), 31 deletions(-) rename src/hotspot/share/utilities/{deferred.hpp => deferredStatic.hpp} (61%) create mode 100644 test/hotspot/gtest/utilities/test_deferredStatic.cpp diff --git a/src/hotspot/share/nmt/memTracker.cpp b/src/hotspot/share/nmt/memTracker.cpp index 3d001bb0b11..ed5d34bc12a 100644 --- a/src/hotspot/share/nmt/memTracker.cpp +++ b/src/hotspot/share/nmt/memTracker.cpp @@ -41,7 +41,7 @@ #include "runtime/vmThread.hpp" #include "utilities/debug.hpp" #include "utilities/defaultStream.hpp" -#include "utilities/deferred.hpp" +#include "utilities/deferredStatic.hpp" #include "utilities/vmError.hpp" #ifdef _WINDOWS @@ -50,7 +50,7 @@ NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown; -Deferred MemTracker::_baseline; +DeferredStatic MemTracker::_baseline; bool MemTracker::NmtVirtualMemoryLocker::_safe_to_use; diff --git a/src/hotspot/share/nmt/memTracker.hpp b/src/hotspot/share/nmt/memTracker.hpp index 8898bf08fa5..124c6163d76 100644 --- a/src/hotspot/share/nmt/memTracker.hpp +++ b/src/hotspot/share/nmt/memTracker.hpp @@ -34,8 +34,8 @@ #include "nmt/virtualMemoryTracker.hpp" #include "runtime/mutexLocker.hpp" #include "utilities/debug.hpp" +#include "utilities/deferredStatic.hpp" #include "utilities/nativeCallStack.hpp" -#include "utilities/deferred.hpp" #define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail) ? \ NativeCallStack(0) : FAKE_CALLSTACK) @@ -319,7 +319,7 @@ class MemTracker : AllStatic { // Tracking level static NMT_TrackingLevel _tracking_level; // Stored baseline - static Deferred _baseline; + static DeferredStatic _baseline; }; #endif // SHARE_NMT_MEMTRACKER_HPP diff --git a/src/hotspot/share/nmt/memoryFileTracker.cpp b/src/hotspot/share/nmt/memoryFileTracker.cpp index 49ef6ef70a0..677cd174650 100644 --- a/src/hotspot/share/nmt/memoryFileTracker.cpp +++ b/src/hotspot/share/nmt/memoryFileTracker.cpp @@ -32,7 +32,7 @@ #include "utilities/nativeCallStack.hpp" #include "utilities/ostream.hpp" -Deferred MemoryFileTracker::Instance::_tracker; +DeferredStatic MemoryFileTracker::Instance::_tracker; MemoryFileTracker::MemoryFileTracker(bool is_detailed_mode) : _stack_storage(is_detailed_mode), _files() {} diff --git a/src/hotspot/share/nmt/memoryFileTracker.hpp b/src/hotspot/share/nmt/memoryFileTracker.hpp index 7800b1a3ba6..1b23dacab81 100644 --- a/src/hotspot/share/nmt/memoryFileTracker.hpp +++ b/src/hotspot/share/nmt/memoryFileTracker.hpp @@ -31,10 +31,10 @@ #include "nmt/vmatree.hpp" #include "nmt/virtualMemoryTracker.hpp" #include "runtime/os.inline.hpp" +#include "utilities/deferredStatic.hpp" #include "utilities/growableArray.hpp" #include "utilities/nativeCallStack.hpp" #include "utilities/ostream.hpp" -#include "utilities/deferred.hpp" // The MemoryFileTracker tracks memory of 'memory files', // storage with its own memory space separate from the process. @@ -92,7 +92,7 @@ class MemoryFileTracker { const GrowableArrayCHeap& files(); class Instance : public AllStatic { - static Deferred _tracker; + static DeferredStatic _tracker; public: diff --git a/src/hotspot/share/utilities/deferred.hpp b/src/hotspot/share/utilities/deferredStatic.hpp similarity index 61% rename from src/hotspot/share/utilities/deferred.hpp rename to src/hotspot/share/utilities/deferredStatic.hpp index a12ca571fe6..43d72d2af41 100644 --- a/src/hotspot/share/utilities/deferred.hpp +++ b/src/hotspot/share/utilities/deferredStatic.hpp @@ -22,17 +22,29 @@ * */ -#ifndef SHARE_UTILITIES_STABLEVALUE_HPP -#define SHARE_UTILITIES_STABLEVALUE_HPP +#ifndef SHARE_UTILITIES_DEFERREDSTATIC_HPP +#define SHARE_UTILITIES_DEFERREDSTATIC_HPP -#include "globalDefinitions.hpp" +#include "utilities/globalDefinitions.hpp" + +#include #include -// The purpose of this class is to defer initialization of a T to a later point in time, -// and then to never deallocate it. This is mainly useful for deferring the initialization of -// static fields in classes, in order to avoid "Static Initialization Order Fiasco". +// The purpose of this class is to provide control over the initialization +// time for an object of type T with static storage duration. An instance of +// this class provides storage for an object, sized and aligned for T. The +// object must be explicitly initialized before use. This avoids problems +// resulting from the unspecified initialization time and ordering between +// different objects that comes from using undeferred objects (the so-called +// "Static Initialization Order Fiasco). +// +// Once initialized, the object is never destroyed. This avoids similar issues +// with the timing and ordering of destruction on normal program exit. +// +// T must not be a reference type. T may be cv-qualified; accessors will +// return a correspondingly cv-qualified reference to the object. template -class Deferred { +class DeferredStatic { union { T _t; }; @@ -40,14 +52,14 @@ class Deferred { DEBUG_ONLY(bool _initialized); public: - NONCOPYABLE(Deferred); + NONCOPYABLE(DeferredStatic); - Deferred() + DeferredStatic() DEBUG_ONLY(: _initialized(false)) { // Do not construct value, on purpose. } - ~Deferred() { + ~DeferredStatic() { // Do not destruct value, on purpose. } @@ -56,27 +68,14 @@ class Deferred { return &_t; } - const T* get() const { - assert(_initialized, "must be initialized before access"); - return &_t; - } - T& operator*() { return *get(); } - const T& operator*() const { - return *get(); - } - T* operator->() { return get(); } - const T* operator->() const { - return get(); - } - template void initialize(Ts&... args) { assert(!_initialized, "Double initialization forbidden"); @@ -86,4 +85,4 @@ class Deferred { } }; -#endif // SHARE_UTILITIES_STABLEVALUE_HPP +#endif // SHARE_UTILITIES_DEFERREDSTATIC_HPP diff --git a/test/hotspot/gtest/utilities/test_deferredStatic.cpp b/test/hotspot/gtest/utilities/test_deferredStatic.cpp new file mode 100644 index 00000000000..b41b1e4ee60 --- /dev/null +++ b/test/hotspot/gtest/utilities/test_deferredStatic.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "utilities/debug.hpp" +#include "utilities/deferredStatic.hpp" +#include "utilities/globalDefinitions.hpp" + +#include + +#include "unittest.hpp" + +class DeferredStaticTestClass { +public: + static unsigned _initialized_count; + int _value; + bool _allow_destruction; + + DeferredStaticTestClass() : DeferredStaticTestClass(0) {} + + DeferredStaticTestClass(int value, bool allow_destruction = false) + : _value(value), _allow_destruction(allow_destruction) + { + ++_initialized_count; + } + + ~DeferredStaticTestClass() { + if (!_allow_destruction) { + ShouldNotReachHere(); + } + } +}; + +unsigned DeferredStaticTestClass::_initialized_count = 0; + +using TC = DeferredStaticTestClass; + +DeferredStatic default_constructed; + +static_assert(std::is_same::value, + "expected"); + +TEST(DeferredStaticTest, default_constructed) { + unsigned init_count = TC::_initialized_count; + default_constructed.initialize(); + ASSERT_EQ(init_count + 1, TC::_initialized_count); + ASSERT_EQ(0, default_constructed->_value); + ASSERT_EQ(0, default_constructed.get()->_value); + ASSERT_EQ(0, (*default_constructed)._value); + + int new_value = 5; + *default_constructed.get() = TC(new_value, true /* allow_destruction */); + ASSERT_EQ(init_count + 2, TC::_initialized_count); + ASSERT_EQ(new_value, default_constructed->_value); + ASSERT_EQ(new_value, default_constructed.get()->_value); + ASSERT_EQ(new_value, (*default_constructed)._value); + + int new_value2 = 8; + default_constructed->_value = new_value2; + ASSERT_EQ(init_count + 2, TC::_initialized_count); + ASSERT_EQ(new_value2, default_constructed->_value); + ASSERT_EQ(new_value2, default_constructed.get()->_value); + ASSERT_EQ(new_value2, (*default_constructed)._value); +} + +DeferredStatic arg_constructed; + +TEST(DeferredStaticTest, arg_constructed) { + unsigned init_count = TC::_initialized_count; + int arg = 10; + arg_constructed.initialize(arg); + ASSERT_EQ(init_count + 1, TC::_initialized_count); + ASSERT_EQ(arg, arg_constructed->_value); + ASSERT_EQ(arg, arg_constructed.get()->_value); + ASSERT_EQ(arg, (*arg_constructed)._value); +} + +DeferredStatic const_test_object; + +static_assert(std::is_same::value, + "expected"); + +static_assert(std::is_same_value)>::value, + "expected"); + +TEST(DeferredStaticTest, const_test_object) { + unsigned init_count = TC::_initialized_count; + int arg = 20; + const_test_object.initialize(arg); + ASSERT_EQ(init_count + 1, TC::_initialized_count); + ASSERT_EQ(arg, const_test_object->_value); + ASSERT_EQ(arg, const_test_object.get()->_value); + ASSERT_EQ(arg, (*const_test_object)._value); + + // Doesn't compile, as expected. + // *const_test_object.get() = TC(0, true /* allow_destruction */); + + // Doesn't compile, as expected. + // const_test_object->_value = 0; +} From a49ecb26c5ff2f949851937f3bb036d7946a103e Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Thu, 26 Jun 2025 15:42:43 +0000 Subject: [PATCH 194/213] 8352635: Improve inferencing of Float16 operations with constant inputs Reviewed-by: epeter, sviswanathan --- src/hotspot/share/opto/convertnode.cpp | 60 +++++ src/hotspot/share/opto/divnode.cpp | 30 +-- src/hotspot/share/opto/subnode.cpp | 15 +- src/hotspot/share/opto/type.hpp | 6 +- .../irTests/TestFloat16ScalarOperations.java | 233 +++++++++++++++--- .../compiler/lib/generators/Generators.java | 23 ++ .../TestFloat16VectorOperations.java | 230 +++++++++++------ 7 files changed, 455 insertions(+), 142 deletions(-) diff --git a/src/hotspot/share/opto/convertnode.cpp b/src/hotspot/share/opto/convertnode.cpp index c468c66fdfd..a495814da61 100644 --- a/src/hotspot/share/opto/convertnode.cpp +++ b/src/hotspot/share/opto/convertnode.cpp @@ -264,8 +264,68 @@ Node* ConvF2HFNode::Ideal(PhaseGVN* phase, bool can_reshape) { return new ReinterpretHF2SNode(binop); } } + + // Detects following ideal graph pattern + // ConvF2HF(binopF(conF, ConvHF2F(varS))) => + // ReinterpretHF2SNode(binopHF(conHF, ReinterpretS2HFNode(varS))) + if (Float16NodeFactory::is_float32_binary_oper(in(1)->Opcode())) { + Node* binopF = in(1); + // Check if the incoming binary operation has one floating point constant + // input and the other input is a half precision to single precision upcasting node. + // We land here because a prior HalfFloat to Float conversion promotes + // an integral constant holding Float16 value to a floating point constant. + // i.e. ConvHF2F ConI(short) => ConF + Node* conF = nullptr; + Node* varS = nullptr; + if (binopF->in(1)->is_Con() && binopF->in(2)->Opcode() == Op_ConvHF2F) { + conF = binopF->in(1); + varS = binopF->in(2)->in(1); + } else if (binopF->in(2)->is_Con() && binopF->in(1)->Opcode() == Op_ConvHF2F) { + conF = binopF->in(2); + varS = binopF->in(1)->in(1); + } + + if (conF != nullptr && + varS != nullptr && + conF->bottom_type()->isa_float_constant() != nullptr && + Matcher::match_rule_supported(Float16NodeFactory::get_float16_binary_oper(binopF->Opcode())) && + Matcher::match_rule_supported(Op_ReinterpretS2HF) && + Matcher::match_rule_supported(Op_ReinterpretHF2S) && + StubRoutines::hf2f_adr() != nullptr && + StubRoutines::f2hf_adr() != nullptr) { + jfloat con = conF->bottom_type()->getf(); + // Conditions under which floating point constant can be considered for a pattern match. + // 1. conF must lie within Float16 value range, otherwise we would have rounding issues: + // Doing the operation in float32 and then rounding is not the same as + // rounding first and doing the operation in float16. + // 2. If a constant value is one of the valid IEEE 754 binary32 NaN bit patterns + // then it's safe to consider it for pattern match because of the following reasons: + // a. As per section 2.8 of JVMS, Java Virtual Machine does not support + // signaling NaN value. + // b. Any signaling NaN which takes part in a non-comparison expression + // results in a quiet NaN but preserves the significand bits of signaling NaN. + // c. The pattern being matched includes a Float to Float16 conversion after binary + // expression, this downcast will still preserve the significand bits of binary32 NaN. + bool isnan = g_isnan((jdouble)con); + if (StubRoutines::hf2f(StubRoutines::f2hf(con)) == con || isnan) { + Node* newVarHF = phase->transform(new ReinterpretS2HFNode(varS)); + Node* conHF = phase->makecon(TypeH::make(con)); + Node* binopHF = nullptr; + // Preserving original input order for semantic correctness + // of non-commutative operation. + if (binopF->in(1) == conF) { + binopHF = phase->transform(Float16NodeFactory::make(binopF->Opcode(), binopF->in(0), conHF, newVarHF)); + } else { + binopHF = phase->transform(Float16NodeFactory::make(binopF->Opcode(), binopF->in(0), newVarHF, conHF)); + } + return new ReinterpretHF2SNode(binopHF); + } + } + } + return nullptr; } + //============================================================================= //------------------------------Value------------------------------------------ const Type* ConvF2INode::Value(PhaseGVN* phase) const { diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp index a77eed208c8..b3ac0a4a1b0 100644 --- a/src/hotspot/share/opto/divnode.cpp +++ b/src/hotspot/share/opto/divnode.cpp @@ -823,39 +823,11 @@ const Type* DivHFNode::Value(PhaseGVN* phase) const { return bot; } - // x/x == 1, we ignore 0/0. - // Note: if t1 and t2 are zero then result is NaN (JVMS page 213) - // Does not work for variables because of NaN's - if (in(1) == in(2) && t1->base() == Type::HalfFloatCon && - !g_isnan(t1->getf()) && g_isfinite(t1->getf()) && t1->getf() != 0.0) { // could be negative ZERO or NaN - return TypeH::ONE; - } - - if (t2 == TypeH::ONE) { - return t1; - } - - // If divisor is a constant and not zero, divide the numbers if (t1->base() == Type::HalfFloatCon && - t2->base() == Type::HalfFloatCon && - t2->getf() != 0.0) { - // could be negative zero + t2->base() == Type::HalfFloatCon) { return TypeH::make(t1->getf() / t2->getf()); } - // If the dividend is a constant zero - // Note: if t1 and t2 are zero then result is NaN (JVMS page 213) - // Test TypeHF::ZERO is not sufficient as it could be negative zero - - if (t1 == TypeH::ZERO && !g_isnan(t2->getf()) && t2->getf() != 0.0) { - return TypeH::ZERO; - } - - // If divisor or dividend is nan then result is nan. - if (g_isnan(t1->getf()) || g_isnan(t2->getf())) { - return TypeH::make(NAN); - } - // Otherwise we give up all hope return Type::HALF_FLOAT; } diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 6451d90eee2..b86ed841e56 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -560,17 +560,12 @@ const Type* SubFPNode::Value(PhaseGVN* phase) const { //------------------------------sub-------------------------------------------- // A subtract node differences its two inputs. const Type* SubHFNode::sub(const Type* t1, const Type* t2) const { - // no folding if one of operands is infinity or NaN, do not do constant folding - if(g_isfinite(t1->getf()) && g_isfinite(t2->getf())) { + // Half precision floating point subtraction follows the rules of IEEE 754 + // applicable to other floating point types. + if (t1->isa_half_float_constant() != nullptr && + t2->isa_half_float_constant() != nullptr) { return TypeH::make(t1->getf() - t2->getf()); - } - else if(g_isnan(t1->getf())) { - return t1; - } - else if(g_isnan(t2->getf())) { - return t2; - } - else { + } else { return Type::HALF_FLOAT; } } diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index f8f523563a0..c61c2a64278 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -302,9 +302,9 @@ class Type { const TypeD *isa_double() const; // Returns null if not a Double{Top,Con,Bot} const TypeD *is_double_constant() const; // Asserts it is a DoubleCon const TypeD *isa_double_constant() const; // Returns null if not a DoubleCon - const TypeH *isa_half_float() const; // Returns null if not a Float{Top,Con,Bot} - const TypeH *is_half_float_constant() const; // Asserts it is a FloatCon - const TypeH *isa_half_float_constant() const; // Returns null if not a FloatCon + const TypeH *isa_half_float() const; // Returns null if not a HalfFloat{Top,Con,Bot} + const TypeH *is_half_float_constant() const; // Asserts it is a HalfFloatCon + const TypeH *isa_half_float_constant() const; // Returns null if not a HalfFloatCon const TypeF *isa_float() const; // Returns null if not a Float{Top,Con,Bot} const TypeF *is_float_constant() const; // Asserts it is a FloatCon const TypeF *isa_float_constant() const; // Returns null if not a FloatCon diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java b/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java index c96146b8e39..c8ee5e730fa 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java @@ -32,10 +32,14 @@ * @run driver TestFloat16ScalarOperations */ import compiler.lib.ir_framework.*; +import compiler.lib.verify.*; import jdk.incubator.vector.Float16; import static jdk.incubator.vector.Float16.*; import java.util.Random; +import compiler.lib.generators.Generator; +import static compiler.lib.generators.Generators.G; + public class TestFloat16ScalarOperations { private static final int count = 1024; @@ -55,19 +59,35 @@ public class TestFloat16ScalarOperations { private static final Float16 MAX_HALF_ULP = Float16.valueOf(16.0f); private static final Float16 SIGNALING_NAN = shortBitsToFloat16((short)31807); - private static Random r = jdk.test.lib.Utils.getRandomInstance(); + private static Generator genF = G.uniformFloats(); + private static Generator genHF = G.uniformFloat16s(); - private static final Float16 RANDOM1 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); - private static final Float16 RANDOM2 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); - private static final Float16 RANDOM3 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); - private static final Float16 RANDOM4 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); - private static final Float16 RANDOM5 = Float16.valueOf(r.nextFloat() * MAX_VALUE.floatValue()); + private static final Float16 RANDOM1 = Float16.valueOf(genF.next()); + private static final Float16 RANDOM2 = Float16.valueOf(genF.next()); + private static final Float16 RANDOM3 = Float16.valueOf(genF.next()); + private static final Float16 RANDOM4 = Float16.valueOf(genF.next()); + private static final Float16 RANDOM5 = Float16.valueOf(genF.next()); private static Float16 RANDOM1_VAR = RANDOM1; private static Float16 RANDOM2_VAR = RANDOM2; private static Float16 RANDOM3_VAR = RANDOM3; private static Float16 RANDOM4_VAR = RANDOM4; private static Float16 RANDOM5_VAR = RANDOM5; + private static Float16 POSITIVE_ZERO_VAR = POSITIVE_ZERO; + + private static final float INEXACT_FP16 = 2051.0f; + private static final float EXACT_FP16 = 2052.0f; + private static final float SNAN_FP16 = Float.intBitsToFloat(0x7F8000F0); + private static final float QNAN_FP16 = Float.intBitsToFloat(0x7FC00000); + + private Float16 GOLDEN_DIV_POT; + private Float16 GOLDEN_MUL2; + private short GOLDEN_INEXACT; + private short GOLDEN_EXACT; + private short GOLDEN_RANDOM_PAT1; + private short GOLDEN_RANDOM_PAT2; + private short GOLDEN_SNAN; + private short GOLDEN_QNAN; public static void main(String args[]) { Scenario s0 = new Scenario(0, "--add-modules=jdk.incubator.vector", "-Xint"); @@ -78,11 +98,19 @@ public static void main(String args[]) { public TestFloat16ScalarOperations() { src = new short[count]; dst = new short[count]; - fl = new float[count]; - for (int i = 0; i < count; i++) { - src[i] = Float.floatToFloat16(r.nextFloat() * MAX_VALUE.floatValue()); - fl[i] = r.nextFloat(); - } + fl = new float[count]; + + G.fill(genF, fl); + G.fill(genHF, src); + + GOLDEN_DIV_POT = testDivByPOT(); + GOLDEN_MUL2 = testMulByTWO(); + GOLDEN_INEXACT = testInexactFP16ConstantPatterns(); + GOLDEN_EXACT = testExactFP16ConstantPatterns(); + GOLDEN_RANDOM_PAT1 = testRandomFP16ConstantPatternSet1(); + GOLDEN_RANDOM_PAT2 = testRandomFP16ConstantPatternSet2(); + GOLDEN_SNAN = testSNaNFP16ConstantPatterns(); + GOLDEN_QNAN = testQNaNFP16ConstantPatterns(); } static void assertResult(float actual, float expected, String msg) { @@ -270,7 +298,7 @@ public void testFma() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MUL_HF, " >0 ", IRNode.REINTERPRET_S2HF, " >0 ", IRNode.REINTERPRET_HF2S, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - public void testDivByPOT() { + public Float16 testDivByPOT() { Float16 res = valueOf(0.0f); for (int i = 0; i < 50; i++) { Float16 divisor = valueOf(8.0f); @@ -281,7 +309,12 @@ public void testDivByPOT() { divisor = valueOf(32.0f); res = add(res, divide(dividend, divisor)); } - dst[0] = float16ToRawShortBits(res); + return res; + } + + @Check(test="testDivByPOT") + public void checkDivByPOT(Float16 actual) { + Verify.checkEQ(Float16.float16ToRawShortBits(GOLDEN_DIV_POT), Float16.float16ToRawShortBits(actual)); } @Test @@ -289,16 +322,151 @@ public void testDivByPOT() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MUL_HF, " 0 ", IRNode.ADD_HF, " >0 ", IRNode.REINTERPRET_S2HF, " >0 ", IRNode.REINTERPRET_HF2S, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) - public void testMulByTWO() { + public Float16 testMulByTWO() { Float16 res = valueOf(0.0f); Float16 multiplier = valueOf(2.0f); for (int i = 0; i < 20; i++) { Float16 multiplicand = valueOf((float)i); res = add(res, multiply(multiplicand, multiplier)); } - assertResult(res.floatValue(), (float)((20 * (20 - 1))/2) * 2.0f, "testMulByTWO"); + return res; + } + + @Check(test="testMulByTWO") + public void checkMulByTWO(Float16 actual) { + Verify.checkEQ(Float16.float16ToRawShortBits(GOLDEN_MUL2), Float16.float16ToRawShortBits(actual)); } + @Test + @IR(counts = {IRNode.ADD_HF, " 0 ", IRNode.SUB_HF, " 0 ", IRNode.MUL_HF, " 0 ", IRNode.DIV_HF, " 0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " 0 ", IRNode.SUB_HF, " 0 ", IRNode.MUL_HF, " 0 ", IRNode.DIV_HF, " 0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + // Test point checks various floating point operations with exactly one floating + // point constant value passed as left or right argument, it then downcasts the + // result of computation to a float16 value. This pattern is used to infer a + // float16 IR during idealization. Floating point constant input is not-representable + // in float16 value range and is an inexact float16 value thereby preventing + // float16 IR inference. + public short testInexactFP16ConstantPatterns() { + short res = 0; + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() + INEXACT_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() - INEXACT_FP16); + res += Float.floatToFloat16(INEXACT_FP16 * POSITIVE_ZERO_VAR.floatValue()); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() / INEXACT_FP16); + return res; + } + + @Check(test="testInexactFP16ConstantPatterns") + public void checkInexactFP16ConstantPatterns(short actual) { + Verify.checkEQ(GOLDEN_INEXACT, actual); + } + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + public short testSNaNFP16ConstantPatterns() { + short res = 0; + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() + SNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() - SNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() * SNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() / SNAN_FP16); + return res; + } + + @Check(test="testSNaNFP16ConstantPatterns") + public void checkSNaNFP16ConstantPatterns(short actual) { + Verify.checkEQ(GOLDEN_SNAN, actual); + } + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + public short testQNaNFP16ConstantPatterns() { + short res = 0; + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() + QNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() - QNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() * QNAN_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() / QNAN_FP16); + return res; + } + + @Check(test="testQNaNFP16ConstantPatterns") + public void checkQNaNFP16ConstantPatterns(short actual) { + Verify.checkEQ(GOLDEN_QNAN, actual); + } + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + // Test point checks various floating point operations with exactly one floating + // point constant value passed as left or right argument, it then downcasts the + // result of computation to a float16 value. This pattern is used to infer a + // Float16 IR during idealization. Floating point constant input is representable + // in Float16 value range thereby leading to a successful Float16 IR inference. + public short testExactFP16ConstantPatterns() { + short res = 0; + res += Float.floatToFloat16(EXACT_FP16 + POSITIVE_ZERO_VAR.floatValue()); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() - EXACT_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() * EXACT_FP16); + res += Float.floatToFloat16(POSITIVE_ZERO_VAR.floatValue() / EXACT_FP16); + return res; + } + + @Check(test="testExactFP16ConstantPatterns") + public void checkExactFP16ConstantPatterns(short actual) { + Verify.checkEQ(GOLDEN_EXACT, actual); + } + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + public short testRandomFP16ConstantPatternSet1() { + short res = 0; + res += Float.floatToFloat16(RANDOM1_VAR.floatValue() + RANDOM2.floatValue()); + res += Float.floatToFloat16(RANDOM2_VAR.floatValue() - RANDOM3.floatValue()); + res += Float.floatToFloat16(RANDOM3_VAR.floatValue() * RANDOM4.floatValue()); + res += Float.floatToFloat16(RANDOM4_VAR.floatValue() / RANDOM5.floatValue()); + return res; + } + + @Check(test="testRandomFP16ConstantPatternSet1") + public void checkRandomFP16ConstantPatternSet1(short actual) { + Verify.checkEQ(GOLDEN_RANDOM_PAT1, actual); + } + + + @Test + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) + @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) + public short testRandomFP16ConstantPatternSet2() { + short res = 0; + res += Float.floatToFloat16(RANDOM2.floatValue() + RANDOM1_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM3.floatValue() - RANDOM2_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM4.floatValue() * RANDOM3_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM5.floatValue() / RANDOM4_VAR.floatValue()); + return res; + } + + @Check(test="testRandomFP16ConstantPatternSet2") + public void checkRandomFP16ConstantPatternSet2(short actual) { + Verify.checkEQ(GOLDEN_RANDOM_PAT2, actual); + } // // Tests points for various Float16 constant folding transforms. Following figure represents various @@ -373,41 +541,42 @@ public void testAddConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.SUB_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testSubConstantFolding() { // If either value is NaN, then the result is NaN. - assertResult(subtract(Float16.NaN, valueOf(2.0f)).floatValue(), Float.NaN, "testAddConstantFolding"); - assertResult(subtract(Float16.NaN, Float16.NaN).floatValue(), Float.NaN, "testAddConstantFolding"); - assertResult(subtract(Float16.NaN, Float16.POSITIVE_INFINITY).floatValue(), Float.NaN, "testAddConstantFolding"); + assertResult(subtract(Float16.NaN, valueOf(2.0f)).floatValue(), Float.NaN, "testSubConstantFolding"); + assertResult(subtract(Float16.NaN, Float16.NaN).floatValue(), Float.NaN, "testSubConstantFolding"); + assertResult(subtract(Float16.NaN, Float16.POSITIVE_INFINITY).floatValue(), Float.NaN, "testSubConstantFolding"); // The difference of two infinities of opposite sign is NaN. - assertResult(subtract(Float16.POSITIVE_INFINITY, Float16.NEGATIVE_INFINITY).floatValue(), Float.POSITIVE_INFINITY, "testAddConstantFolding"); + assertResult(subtract(Float16.POSITIVE_INFINITY, Float16.NEGATIVE_INFINITY).floatValue(), Float.POSITIVE_INFINITY, "testSubConstantFolding"); // The difference of two infinities of the same sign is NaN. - assertResult(subtract(Float16.POSITIVE_INFINITY, Float16.POSITIVE_INFINITY).floatValue(), Float.NaN, "testAddConstantFolding"); - assertResult(subtract(Float16.NEGATIVE_INFINITY, Float16.NEGATIVE_INFINITY).floatValue(), Float.NaN, "testAddConstantFolding"); + assertResult(subtract(Float16.POSITIVE_INFINITY, Float16.POSITIVE_INFINITY).floatValue(), Float.NaN, "testSubConstantFolding"); + assertResult(subtract(Float16.NEGATIVE_INFINITY, Float16.NEGATIVE_INFINITY).floatValue(), Float.NaN, "testSubConstantFolding"); // The difference of an infinity and a finite value is equal to the infinite operand. - assertResult(subtract(Float16.POSITIVE_INFINITY, valueOf(2.0f)).floatValue(), Float.POSITIVE_INFINITY, "testAddConstantFolding"); - assertResult(subtract(Float16.NEGATIVE_INFINITY, valueOf(2.0f)).floatValue(), Float.NEGATIVE_INFINITY, "testAddConstantFolding"); + assertResult(subtract(Float16.POSITIVE_INFINITY, valueOf(2.0f)).floatValue(), Float.POSITIVE_INFINITY, "testSubConstantFolding"); + assertResult(subtract(Float16.NEGATIVE_INFINITY, valueOf(2.0f)).floatValue(), Float.NEGATIVE_INFINITY, "testSubConstantFolding"); // The difference of two zeros of opposite sign is positive zero. - assertResult(subtract(NEGATIVE_ZERO, POSITIVE_ZERO).floatValue(), 0.0f, "testAddConstantFolding"); + assertResult(subtract(NEGATIVE_ZERO, POSITIVE_ZERO).floatValue(), 0.0f, "testSubConstantFolding"); // Number equal to -MAX_VALUE when subtracted by half upl of MAX_VALUE results into -Inf. - assertResult(subtract(NEGATIVE_MAX_VALUE, MAX_HALF_ULP).floatValue(), Float.NEGATIVE_INFINITY, "testAddConstantFolding"); + assertResult(subtract(NEGATIVE_MAX_VALUE, MAX_HALF_ULP).floatValue(), Float.NEGATIVE_INFINITY, "testSubConstantFolding"); // Number equal to -MAX_VALUE when subtracted by a number less than half upl for MAX_VALUE results into -MAX_VALUE. - assertResult(subtract(NEGATIVE_MAX_VALUE, LT_MAX_HALF_ULP).floatValue(), NEGATIVE_MAX_VALUE.floatValue(), "testAddConstantFolding"); + assertResult(subtract(NEGATIVE_MAX_VALUE, LT_MAX_HALF_ULP).floatValue(), NEGATIVE_MAX_VALUE.floatValue(), "testSubConstantFolding"); - assertResult(subtract(valueOf(1.0f), valueOf(2.0f)).floatValue(), -1.0f, "testAddConstantFolding"); + assertResult(subtract(valueOf(1.0f), valueOf(2.0f)).floatValue(), -1.0f, "testSubConstantFolding"); } @Test - @Warmup(value = 10000) @IR(counts = {IRNode.MAX_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MAX_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testMaxConstantFolding() { // If either value is NaN, then the result is NaN. assertResult(max(valueOf(2.0f), Float16.NaN).floatValue(), Float.NaN, "testMaxConstantFolding"); @@ -428,6 +597,7 @@ public void testMaxConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MIN_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testMinConstantFolding() { // If either value is NaN, then the result is NaN. assertResult(min(valueOf(2.0f), Float16.NaN).floatValue(), Float.NaN, "testMinConstantFolding"); @@ -447,6 +617,7 @@ public void testMinConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.DIV_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testDivConstantFolding() { // If either value is NaN, then the result is NaN. assertResult(divide(Float16.NaN, POSITIVE_ZERO).floatValue(), Float.NaN, "testDivConstantFolding"); @@ -489,6 +660,7 @@ public void testDivConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.MUL_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testMulConstantFolding() { // If any operand is NaN, the result is NaN. assertResult(multiply(Float16.NaN, valueOf(4.0f)).floatValue(), Float.NaN, "testMulConstantFolding"); @@ -514,6 +686,7 @@ public void testMulConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.SQRT_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testSqrtConstantFolding() { // If the argument is NaN or less than zero, then the result is NaN. assertResult(sqrt(Float16.NaN).floatValue(), Float.NaN, "testSqrtConstantFolding"); @@ -535,6 +708,7 @@ public void testSqrtConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.FMA_HF, " 0 ", IRNode.REINTERPRET_S2HF, " 0 ", IRNode.REINTERPRET_HF2S, " 0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testFMAConstantFolding() { // If any argument is NaN, the result is NaN. assertResult(fma(Float16.NaN, valueOf(2.0f), valueOf(3.0f)).floatValue(), Float.NaN, "testFMAConstantFolding"); @@ -572,6 +746,7 @@ public void testFMAConstantFolding() { applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(failOn = {IRNode.ADD_HF, IRNode.SUB_HF, IRNode.MUL_HF, IRNode.DIV_HF, IRNode.SQRT_HF, IRNode.FMA_HF}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testRounding1() { dst[0] = float16ToRawShortBits(add(RANDOM1, RANDOM2)); dst[1] = float16ToRawShortBits(subtract(RANDOM2, RANDOM3)); @@ -608,13 +783,13 @@ public void checkRounding1() { } @Test - @Warmup(value = 10000) @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 ", IRNode.SQRT_HF, " >0 ", IRNode.FMA_HF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zfh", "true"}) @IR(counts = {IRNode.ADD_HF, " >0 ", IRNode.SUB_HF, " >0 ", IRNode.MUL_HF, " >0 ", IRNode.DIV_HF, " >0 ", IRNode.SQRT_HF, " >0 ", IRNode.FMA_HF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + @Warmup(10000) public void testRounding2() { dst[0] = float16ToRawShortBits(add(RANDOM1_VAR, RANDOM2_VAR)); dst[1] = float16ToRawShortBits(subtract(RANDOM2_VAR, RANDOM3_VAR)); diff --git a/test/hotspot/jtreg/compiler/lib/generators/Generators.java b/test/hotspot/jtreg/compiler/lib/generators/Generators.java index ac4062f19d5..c16b35cdae8 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/Generators.java +++ b/test/hotspot/jtreg/compiler/lib/generators/Generators.java @@ -605,6 +605,29 @@ public void fill(Generator generator, float[] a) { fillFloat(generator, MemorySegment.ofArray(a)); } + /** + * Fills the memory segments with shorts obtained by calling next on the generator. + * + * @param generator The generator from which to source the values. + * @param ms Memory segment to be filled with random values. + */ + public void fillShort(Generator generator, MemorySegment ms) { + var layout = ValueLayout.JAVA_SHORT_UNALIGNED; + for (long i = 0; i < ms.byteSize() / layout.byteSize(); i++) { + ms.setAtIndex(layout, i, generator.next()); + } + } + + /** + * Fill the array with shorts using the distribution of the generator. + * + * @param a Array to be filled with random values. + */ + public void fill(Generator generator, short[] a) { + fillShort(generator, MemorySegment.ofArray(a)); + } + + /** * Fills the memory segments with ints obtained by calling next on the generator. * diff --git a/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java b/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java index a0622d665b8..9c342574632 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestFloat16VectorOperations.java @@ -37,6 +37,7 @@ import jdk.incubator.vector.Float16; import static jdk.incubator.vector.Float16.*; import static java.lang.Float.*; +import java.util.Arrays; import jdk.test.lib.*; import compiler.lib.generators.Generator; import static compiler.lib.generators.Generators.G; @@ -46,9 +47,11 @@ public class TestFloat16VectorOperations { private short[] input2; private short[] input3; private short[] output; - private static short SCALAR_FP16 = (short)0x7777; + private static short FP16_SCALAR = (short)0x7777; private static final int LEN = 2048; + private static final Float16 FP16_CONST = Float16.valueOf(1023.0f); + public static void main(String args[]) { // Test with default MaxVectorSize TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); @@ -60,10 +63,14 @@ public static void main(String args[]) { TestFramework.runWithFlags("--add-modules=jdk.incubator.vector", "-XX:MaxVectorSize=64"); } - public static boolean assertResults(short expected, short actual) { - Float16 expected_fp16 = shortBitsToFloat16(expected); - Float16 actual_fp16 = shortBitsToFloat16(actual); - return !expected_fp16.equals(actual_fp16); + public static void assertResults(int arity, short ... values) { + assert values.length == (arity + 2); + Float16 expected_fp16 = shortBitsToFloat16(values[arity]); + Float16 actual_fp16 = shortBitsToFloat16(values[arity + 1]); + if(!expected_fp16.equals(actual_fp16)) { + String inputs = Arrays.toString(Arrays.copyOfRange(values, 0, arity - 1)); + throw new AssertionError("Result Mismatch!, input = " + inputs + " actual = " + actual_fp16 + " expected = " + expected_fp16); + } } public TestFloat16VectorOperations() { @@ -84,9 +91,9 @@ public TestFloat16VectorOperations() { @Test @Warmup(50) - @IR(counts = {IRNode.ADD_VHF, ">= 1"}, + @IR(counts = {IRNode.ADD_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.ADD_VHF, ">= 1"}, + @IR(counts = {IRNode.ADD_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorAddFloat16() { for (int i = 0; i < LEN; ++i) { @@ -98,18 +105,16 @@ public void vectorAddFloat16() { public void checkResultAdd() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(float16ToFloat(input1[i]) + float16ToFloat(input2[i])); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } + @Test @Warmup(50) - @IR(counts = {IRNode.SUB_VHF, ">= 1"}, + @IR(counts = {IRNode.SUB_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.SUB_VHF, ">= 1"}, + @IR(counts = {IRNode.SUB_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorSubFloat16() { for (int i = 0; i < LEN; ++i) { @@ -121,18 +126,16 @@ public void vectorSubFloat16() { public void checkResultSub() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(float16ToFloat(input1[i]) - float16ToFloat(input2[i])); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } + @Test @Warmup(50) - @IR(counts = {IRNode.MUL_VHF, ">= 1"}, + @IR(counts = {IRNode.MUL_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.MUL_VHF, ">= 1"}, + @IR(counts = {IRNode.MUL_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorMulFloat16() { for (int i = 0; i < LEN; ++i) { @@ -144,18 +147,15 @@ public void vectorMulFloat16() { public void checkResultMul() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(float16ToFloat(input1[i]) * float16ToFloat(input2[i])); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.DIV_VHF, ">= 1"}, + @IR(counts = {IRNode.DIV_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.DIV_VHF, ">= 1"}, + @IR(counts = {IRNode.DIV_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorDivFloat16() { for (int i = 0; i < LEN; ++i) { @@ -167,18 +167,15 @@ public void vectorDivFloat16() { public void checkResultDiv() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(float16ToFloat(input1[i]) / float16ToFloat(input2[i])); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.MIN_VHF, ">= 1"}, + @IR(counts = {IRNode.MIN_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.MIN_VHF, ">= 1"}, + @IR(counts = {IRNode.MIN_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorMinFloat16() { for (int i = 0; i < LEN; ++i) { @@ -190,18 +187,15 @@ public void vectorMinFloat16() { public void checkResultMin() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(Math.min(float16ToFloat(input1[i]), float16ToFloat(input2[i]))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.MAX_VHF, ">= 1"}, + @IR(counts = {IRNode.MAX_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.MAX_VHF, ">= 1"}, + @IR(counts = {IRNode.MAX_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorMaxFloat16() { for (int i = 0; i < LEN; ++i) { @@ -213,18 +207,15 @@ public void vectorMaxFloat16() { public void checkResultMax() { for (int i = 0; i < LEN; ++i) { short expected = floatToFloat16(Math.max(float16ToFloat(input1[i]), float16ToFloat(input2[i]))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], input2[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.SQRT_VHF, ">= 1"}, + @IR(counts = {IRNode.SQRT_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.SQRT_VHF, ">= 1"}, + @IR(counts = {IRNode.SQRT_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorSqrtFloat16() { for (int i = 0; i < LEN; ++i) { @@ -236,18 +227,15 @@ public void vectorSqrtFloat16() { public void checkResultSqrt() { for (int i = 0; i < LEN; ++i) { short expected = float16ToRawShortBits(sqrt(shortBitsToFloat16(input1[i]))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input = " + input1[i] + - " output = " + output[i] + " expected = " + expected); - } + assertResults(1, input1[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.FMA_VHF, ">= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.FMA_VHF, ">= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorFmaFloat16() { for (int i = 0; i < LEN; ++i) { @@ -261,22 +249,19 @@ public void checkResultFma() { for (int i = 0; i < LEN; ++i) { short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), shortBitsToFloat16(input3[i]))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - "input3 = " + input3[i] + " output = " + output[i] + " expected = " + expected); - } + assertResults(3, input1[i], input2[i], input3[i], expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.FMA_VHF, " >= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.FMA_VHF, ">= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorFmaFloat16ScalarMixedConstants() { for (int i = 0; i < LEN; ++i) { - output[i] = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(SCALAR_FP16), + output[i] = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(FP16_SCALAR), shortBitsToFloat16(floatToFloat16(3.0f)))); } } @@ -284,21 +269,18 @@ public void vectorFmaFloat16ScalarMixedConstants() { @Check(test="vectorFmaFloat16ScalarMixedConstants") public void checkResultFmaScalarMixedConstants() { for (int i = 0; i < LEN; ++i) { - short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(SCALAR_FP16), + short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(FP16_SCALAR), shortBitsToFloat16(floatToFloat16(3.0f)))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + SCALAR_FP16 + - "input3 = 3.0 " + "output = " + output[i] + " expected = " + expected); - } + assertResults(2, input1[i], FP16_SCALAR, expected, output[i]); } } @Test @Warmup(50) - @IR(counts = {IRNode.FMA_VHF, " >= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) - @IR(counts = {IRNode.FMA_VHF, ">= 1"}, + @IR(counts = {IRNode.FMA_VHF, " >0 "}, applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) public void vectorFmaFloat16MixedConstants() { short input3 = floatToFloat16(3.0f); @@ -307,15 +289,13 @@ public void vectorFmaFloat16MixedConstants() { } } + @Check(test="vectorFmaFloat16MixedConstants") public void checkResultFmaMixedConstants() { short input3 = floatToFloat16(3.0f); for (int i = 0; i < LEN; ++i) { short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1[i]), shortBitsToFloat16(input2[i]), shortBitsToFloat16(input3))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1[i] + " input2 = " + input2[i] + - "input3 = " + input3 + " output = " + output[i] + " expected = " + expected); - } + assertResults(3, input1[i], input2[i], input3, expected, output[i]); } } @@ -341,10 +321,118 @@ public void checkResultFmaAllConstants() { short input3 = floatToFloat16(3.0f); for (int i = 0; i < LEN; ++i) { short expected = float16ToRawShortBits(fma(shortBitsToFloat16(input1), shortBitsToFloat16(input2), shortBitsToFloat16(input3))); - if (assertResults(expected, output[i])) { - throw new RuntimeException("Invalid result: [" + i + "] input1 = " + input1 + " input2 = " + input2 + - "input3 = " + input3 + " output = " + output[i] + " expected = " + expected); - } + assertResults(3, input1, input2, input3, expected, output[i]); + } + } + + + @Test + @Warmup(50) + @IR(counts = {IRNode.ADD_VHF, " >0 "}, + applyIfCPUFeatureOr = {"avx512_fp16", "true", "zvfh", "true", "sve", "true"}) + @IR(counts = {IRNode.ADD_VHF, " >0 "}, + applyIfCPUFeatureAnd = {"fphp", "true", "asimdhp", "true"}) + public void vectorAddConstInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(add(shortBitsToFloat16(input1[i]), FP16_CONST)); + } + } + + @Check(test="vectorAddConstInputFloat16") + public void checkResultAddConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) + FP16_CONST.floatValue()); + assertResults(2, input1[i], float16ToRawShortBits(FP16_CONST), expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.SUB_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorSubConstInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(subtract(shortBitsToFloat16(input1[i]), FP16_CONST)); + } + } + + @Check(test="vectorSubConstInputFloat16") + public void checkResultSubConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(float16ToFloat(input1[i]) - FP16_CONST.floatValue()); + assertResults(2, input1[i], float16ToRawShortBits(FP16_CONST), expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.MUL_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorMulConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(multiply(FP16_CONST, shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorMulConstantInputFloat16") + public void checkResultMulConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(FP16_CONST.floatValue() * float16ToFloat(input2[i])); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.DIV_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorDivConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(divide(FP16_CONST, shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorDivConstantInputFloat16") + public void checkResultDivConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(FP16_CONST.floatValue() / float16ToFloat(input2[i])); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.MAX_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorMaxConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(max(FP16_CONST, shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorMaxConstantInputFloat16") + public void checkResultMaxConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.max(FP16_CONST.floatValue(), float16ToFloat(input2[i]))); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); + } + } + + @Test + @Warmup(50) + @IR(counts = {IRNode.MIN_VHF, " >0 "}, + applyIfCPUFeature = {"avx512_fp16", "true"}) + public void vectorMinConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + output[i] = float16ToRawShortBits(min(FP16_CONST, shortBitsToFloat16(input2[i]))); + } + } + + @Check(test="vectorMinConstantInputFloat16") + public void checkResultMinConstantInputFloat16() { + for (int i = 0; i < LEN; ++i) { + short expected = floatToFloat16(Math.min(FP16_CONST.floatValue(), float16ToFloat(input2[i]))); + assertResults(2, float16ToRawShortBits(FP16_CONST), input2[i], expected, output[i]); } } } From 83fe688d809ca783f8ebf6528a1cf4540d698fb1 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 26 Jun 2025 16:35:43 +0000 Subject: [PATCH 195/213] 8360554: Use the title from the JSON RFC for the @spec tag Reviewed-by: alanb, kevinw --- .../classes/com/sun/management/HotSpotDiagnosticMXBean.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java index 067cfffb158..8ce7c03f62d 100644 --- a/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java +++ b/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java @@ -158,7 +158,8 @@ public static enum ThreadDumpFormat { TEXT_PLAIN, /** * JSON (JavaScript Object Notation) format. - * @spec https://datatracker.ietf.org/doc/html/rfc8259 JavaScript Object Notation + * @spec https://datatracker.ietf.org/doc/html/rfc8259 RFC 8259: The JavaScript + * Object Notation (JSON) Data Interchange Format */ JSON, } From 20e0055e202e523b40e8b066e2f71c21d8cc5ea9 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 26 Jun 2025 17:23:55 +0000 Subject: [PATCH 196/213] 8344165: Trace exceptions with a complete call-stack Reviewed-by: coleenp, dholmes --- .../share/interpreter/interpreterRuntime.cpp | 4 ++ src/hotspot/share/utilities/exceptions.cpp | 62 +++++++++++++++--- src/hotspot/share/utilities/exceptions.hpp | 4 +- .../jtreg/runtime/logging/ExceptionsTest.java | 63 ++++++++++++++++--- .../logging/ExceptionsTest_options_file | 2 +- 5 files changed, 117 insertions(+), 18 deletions(-) diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index fcc0b96efa4..8e7e5772ba6 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -500,6 +500,10 @@ JRT_ENTRY(address, InterpreterRuntime::exception_handler_for_exception(JavaThrea h_method->print_value_string(), current_bci, p2i(current), current->name()); Exceptions::log_exception(h_exception, tempst.as_string()); } + if (log_is_enabled(Info, exceptions, stacktrace)) { + Exceptions::log_exception_stacktrace(h_exception, h_method, current_bci); + } + // Don't go paging in something which won't be used. // else if (extable->length() == 0) { // // disabled for now - interpreter is not using shortcut yet diff --git a/src/hotspot/share/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp index c48b33b1e1f..fd1a2930034 100644 --- a/src/hotspot/share/utilities/exceptions.cpp +++ b/src/hotspot/share/utilities/exceptions.cpp @@ -114,15 +114,17 @@ bool Exceptions::special_exception(JavaThread* thread, const char* file, int lin #endif // ASSERT if (h_exception.is_null() && !thread->can_call_java()) { - ResourceMark rm(thread); - const char* exc_value = h_name != nullptr ? h_name->as_C_string() : "null"; - log_info(exceptions)("Thread cannot call Java so instead of throwing exception <%.*s%s%.*s> (" PTR_FORMAT ") \n" - "at [%s, line %d]\nfor thread " PTR_FORMAT ",\n" - "throwing pre-allocated exception: %s", - MAX_LEN, exc_value, message ? ": " : "", - MAX_LEN, message ? message : "", - p2i(h_exception()), file, line, p2i(thread), - Universe::vm_exception()->print_value_string()); + if (log_is_enabled(Info, exceptions)) { + ResourceMark rm(thread); + const char* exc_value = h_name != nullptr ? h_name->as_C_string() : "null"; + log_info(exceptions)("Thread cannot call Java so instead of throwing exception <%.*s%s%.*s> (" PTR_FORMAT ") \n" + "at [%s, line %d]\nfor thread " PTR_FORMAT ",\n" + "throwing pre-allocated exception: %s", + MAX_LEN, exc_value, message ? ": " : "", + MAX_LEN, message ? message : "", + p2i(h_exception()), file, line, p2i(thread), + Universe::vm_exception()->print_value_string()); + } // We do not care what kind of exception we get for a thread which // is compiling. We just install a dummy exception object thread->set_pending_exception(Universe::vm_exception(), file, line); @@ -152,6 +154,9 @@ void Exceptions::_throw(JavaThread* thread, const char* file, int line, Handle h message ? ": " : "", MAX_LEN, message ? message : "", p2i(h_exception()), file, line, p2i(thread)); + if (log_is_enabled(Info, exceptions, stacktrace)) { + log_exception_stacktrace(h_exception); + } // for AbortVMOnException flag Exceptions::debug_check_abort(h_exception, message); @@ -609,3 +614,42 @@ void Exceptions::log_exception(Handle exception, const char* message) { MAX_LEN, message); } } + +// This is called from InterpreterRuntime::exception_handler_for_exception(), which is the only +// easy way to be notified in the VM that an _athrow bytecode has been executed. (The alternative +// would be to add hooks into the interpreter and compiler, for all platforms ...). +// +// Unfortunately, InterpreterRuntime::exception_handler_for_exception() is called for every level +// of the Java stack when looking for an exception handler. To avoid excessive output, +// we print the stack only when the bci points to an _athrow bytecode. +// +// NOTE: exceptions that are NOT thrown by _athrow are handled by Exceptions::special_exception() +// and Exceptions::_throw()). +void Exceptions::log_exception_stacktrace(Handle exception, methodHandle method, int bci) { + if (!method->is_native() && (Bytecodes::Code) *method->bcp_from(bci) == Bytecodes::_athrow) { + // TODO: try to find a way to avoid repeated stacktraces when an exception gets re-thrown + // by a finally block + log_exception_stacktrace(exception); + } +} + +// This should be called only from a live Java thread. +void Exceptions::log_exception_stacktrace(Handle exception) { + LogStreamHandle(Info, exceptions, stacktrace) st; + ResourceMark rm; + const char* detail_message = java_lang_Throwable::message_as_utf8(exception()); + if (detail_message != nullptr) { + st.print_cr("Exception <%.*s: %.*s>", + MAX_LEN, exception->print_value_string(), + MAX_LEN, detail_message); + } else { + st.print_cr("Exception <%.*s>", + MAX_LEN, exception->print_value_string()); + } + JavaThread* t = JavaThread::current(); + if (t->has_last_Java_frame()) { + t->print_active_stack_on(&st); + } else { + st.print_cr("(Cannot print stracktrace)"); + } +} diff --git a/src/hotspot/share/utilities/exceptions.hpp b/src/hotspot/share/utilities/exceptions.hpp index 0dca7971ef9..94f4a04546d 100644 --- a/src/hotspot/share/utilities/exceptions.hpp +++ b/src/hotspot/share/utilities/exceptions.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -190,6 +190,8 @@ class Exceptions { // for logging exceptions static void log_exception(Handle exception, const char* message); + static void log_exception_stacktrace(Handle exception); + static void log_exception_stacktrace(Handle exception, methodHandle method, int bci); }; diff --git a/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java b/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java index 327b1cc0f24..c2c966cb047 100644 --- a/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java +++ b/test/hotspot/jtreg/runtime/logging/ExceptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8141211 8147477 + * @bug 8141211 8147477 8358080 * @summary exceptions=info output should have an exception message for interpreter methods * @requires vm.flagless * @library /test/lib @@ -34,6 +34,8 @@ import java.io.File; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; @@ -44,10 +46,24 @@ static void updateEnvironment(ProcessBuilder pb, String environmentVariable, Str } static void analyzeOutputOn(ProcessBuilder pb) throws Exception { - OutputAnalyzer output = new OutputAnalyzer(pb.start()); + OutputAnalyzer output = ProcessTools.executeProcess(pb); output.shouldContain(""); output.shouldContain(" thrown in interpreter method "); - output.shouldHaveExitValue(0); + output.shouldMatch("info..exceptions,stacktrace.*at ExceptionsTest[$]InternalClass.bar[(]ExceptionsTest.java:[0-9]+" + + ".*\n.*" + + "info..exceptions,stacktrace.*at ExceptionsTest[$]InternalClass.foo[(]ExceptionsTest.java:[0-9]+" + + ".*\n.*" + + "info..exceptions,stacktrace.*at ExceptionsTest[$]InternalClass.main[(]ExceptionsTest.java:[0-9]+"); + + // Note: "(?s)" means that the "." in the regexp can match the newline character. + // To avoid verbosity, stack trace for bar2()->baz2() should be printed only once: + // - It should be printed when the exception is thrown inside bzz2() + // - It should not be printed when the interpreter is looking for an exception handler inside bar2() + output.shouldMatch("(?s)baz2.*bar2"); + output.shouldNotMatch("(?s)baz2.*bar2,*baz2.*bar2"); + + // Two stack traces should include main()->foo2(), as an exception is thrown at two different BCIs in bar2(). + output.shouldMatch("(?s)foo2.*main.*foo2.*main"); } static void analyzeOutputOff(ProcessBuilder pb) throws Exception { @@ -57,7 +73,7 @@ static void analyzeOutputOff(ProcessBuilder pb) throws Exception { } public static void main(String[] args) throws Exception { - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:exceptions=info", + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:exceptions,exceptions+stacktrace", InternalClass.class.getName()); analyzeOutputOn(pb); @@ -66,7 +82,7 @@ public static void main(String[] args) throws Exception { analyzeOutputOff(pb); pb = ProcessTools.createLimitedTestJavaProcessBuilder(InternalClass.class.getName()); - updateEnvironment(pb, "_JAVA_OPTIONS", "-Xlog:exceptions=info"); + updateEnvironment(pb, "_JAVA_OPTIONS", "-Xlog:exceptions,exceptions+stacktrace"); analyzeOutputOn(pb); pb = ProcessTools.createLimitedTestJavaProcessBuilder(InternalClass.class.getName()); @@ -80,12 +96,45 @@ public static void main(String[] args) throws Exception { } public static class InternalClass { - public static void main(String[] args) throws Exception { + public static void main(String[] args) { + foo(); + foo2(); + } + + static void foo() { + bar(); + } + + static void bar() { try { throw new RuntimeException("Test exception 1 for logging"); } catch (Exception e) { System.out.println("Exception 1 caught."); } } + + static void foo2() { + try { + bar2(); + } catch (Exception e) { + System.out.println("Exception 2 caught."); + } + } + + static void bar2() { + try { + baz2(); + } catch (RuntimeException e) { + throw e; // Rethrow -- should print a new callstack. + } + } + + static void baz2() { + bzz2(); + } + + static void bzz2() { + throw new RuntimeException("Test exception 2 for logging"); + } } } diff --git a/test/hotspot/jtreg/runtime/logging/ExceptionsTest_options_file b/test/hotspot/jtreg/runtime/logging/ExceptionsTest_options_file index d3e8be7f857..1b566aaa456 100644 --- a/test/hotspot/jtreg/runtime/logging/ExceptionsTest_options_file +++ b/test/hotspot/jtreg/runtime/logging/ExceptionsTest_options_file @@ -1 +1 @@ --Xlog:exceptions=info +-Xlog:exceptions,exceptions+stacktrace From 334683e634c23a3672585e4309a528d0944d942e Mon Sep 17 00:00:00 2001 From: David Holmes Date: Thu, 26 Jun 2025 21:48:46 +0000 Subject: [PATCH 197/213] 8358645: Access violation in ThreadsSMRSupport::print_info_on during thread dump Reviewed-by: fbredberg, shade, dcubed --- src/hotspot/share/runtime/threadSMR.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/runtime/threadSMR.cpp b/src/hotspot/share/runtime/threadSMR.cpp index bcfd950ee39..631a7ed8d79 100644 --- a/src/hotspot/share/runtime/threadSMR.cpp +++ b/src/hotspot/share/runtime/threadSMR.cpp @@ -1168,9 +1168,10 @@ void ThreadsSMRSupport::print_info_on(const Thread* thread, outputStream* st) { // The count is only interesting if we have a _threads_list_ptr. st->print(", _nested_threads_hazard_ptr_cnt=%u", thread->_nested_threads_hazard_ptr_cnt); } - if (SafepointSynchronize::is_at_safepoint() || Thread::current() == thread) { - // It is only safe to walk the list if we're at a safepoint or the - // calling thread is walking its own list. + if ((SafepointSynchronize::is_at_safepoint() && thread->is_Java_thread()) || + Thread::current() == thread) { + // It is only safe to walk the list if we're at a safepoint and processing a JavaThread, + // or the calling thread is walking its own list. SafeThreadsListPtr* current = thread->_threads_list_ptr; if (current != nullptr) { // Skip the top nesting level as it is always printed above. From 8ea544c33fc502208577249fb83544f8d876bc17 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 26 Jun 2025 22:18:56 +0000 Subject: [PATCH 198/213] 8360287: JFR: PlatformTracer class should be loaded lazily Reviewed-by: mgronlun --- .../classes/jdk/jfr/internal/JDKEvents.java | 3 +- .../jfr/internal/settings/MethodSetting.java | 15 ++++++ .../jfr/internal/tracing/PlatformTracer.java | 13 +----- .../event/tracing/TestLazyPlatformTracer.java | 46 +++++++++++++++++++ 4 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 test/jdk/jdk/jfr/event/tracing/TestLazyPlatformTracer.java diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java index a28f1fdd41f..503a7955e00 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JDKEvents.java @@ -45,6 +45,7 @@ import jdk.jfr.events.MethodTimingEvent; import jdk.jfr.events.MethodTraceEvent; import jdk.jfr.internal.periodic.PeriodicEvents; +import jdk.jfr.internal.settings.MethodSetting; import jdk.jfr.internal.tracing.PlatformTracer; import jdk.jfr.tracing.MethodTracer; @@ -235,7 +236,7 @@ private static void emitInitialSecurityProperties() { } private static void emitMethodTiming() { - if (MethodTimingEvent.enabled()) { + if (MethodSetting.isInitialized() && MethodTimingEvent.enabled()) { PlatformTracer.emitTiming(); } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java index f3e1069ca21..0f2751b6ac7 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/settings/MethodSetting.java @@ -42,6 +42,7 @@ @Name(Type.SETTINGS_PREFIX + "Filter") public final class MethodSetting extends FilterSetting { private final Modification modification; + private volatile static boolean initialized; public MethodSetting(PlatformEventType eventType, Modification modification, String defaultValue) { super(eventType, defaultValue); @@ -55,6 +56,20 @@ public boolean isValid(String text) { @Override protected void apply(PlatformEventType eventType, List filters) { + ensureInitialized(); PlatformTracer.setFilters(modification, filters); } + + // Expected to be called when holding external lock, so no extra + // synchronization is required here. + private static void ensureInitialized() { + if (!initialized) { + PlatformTracer.initialize(); + initialized = true; + } + } + + public static boolean isInitialized() { + return initialized; + } } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java index 5985b28b58e..2d40e496dc1 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tracing/PlatformTracer.java @@ -53,8 +53,6 @@ public final class PlatformTracer { private static List timingFilters = List.of(); private static TimedMethod OBJECT; - private static boolean initialized; - public static byte[] onMethodTrace(Module module, ClassLoader classLoader, String className, byte[] oldBytecode, long[] ids, String[] names, String[] signatures, int[] modifications) { @@ -159,7 +157,6 @@ public static void addTiming(long id, long duration) { } public static void setFilters(Modification modification, List filters) { - ensureInitialized(); publishClasses(applyFilter(modification, filters)); } @@ -252,14 +249,6 @@ private static void reset() { timedClasses.clear(); } - // Expected to be called when holding external lock, so no extra - // synchronization is required here. - private static void ensureInitialized() { - if (!initialized) { - initialize(); - initialized = true; - } - } // This method has three purposes: // @@ -274,7 +263,7 @@ private static void ensureInitialized() { // This method takes 1-10 milliseconds to run and is only executed once, // provided a user has specified a non-empty filter for the MethodTrace or // MethodTiming event. - private static void initialize() { + public static void initialize() { try { Logger.log(LogTag.JFR_METHODTRACE, LogLevel.DEBUG, "Method tracer initialization started."); Thread current = Thread.currentThread(); diff --git a/test/jdk/jdk/jfr/event/tracing/TestLazyPlatformTracer.java b/test/jdk/jdk/jfr/event/tracing/TestLazyPlatformTracer.java new file mode 100644 index 00000000000..d3e6146bc74 --- /dev/null +++ b/test/jdk/jdk/jfr/event/tracing/TestLazyPlatformTracer.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.jfr.event.tracing; + +import jdk.internal.misc.Unsafe; +import jdk.jfr.FlightRecorder; +import jdk.jfr.Recording; +/** +* @test +* @summary Tests that PlatformTracer is not initialized if a method filter has not been set. +* @requires vm.flagless +* @requires vm.hasJFR +* @modules java.base/jdk.internal.misc jdk.jfr/jdk.jfr.internal.tracing +* @library /test/lib +* @run main/othervm -XX:StartFlightRecording jdk.jfr.event.tracing.TestLazyPlatformTracer +*/ +public class TestLazyPlatformTracer { + + public static void main(String... args) throws Exception { + // Stop recording so end chunk events are emitted + FlightRecorder.getFlightRecorder().getRecordings().getFirst().stop(); + if (!Unsafe.getUnsafe().shouldBeInitialized(jdk.jfr.internal.tracing.PlatformTracer.class)) { + throw new AssertionError("PlatformTracer should not have been initialized"); + } + } +} From 6d05a1d3f492b6f06b603ae2bb0d03dfb6c8b8f2 Mon Sep 17 00:00:00 2001 From: Luigi Montoya Date: Fri, 27 Jun 2025 06:11:33 +0000 Subject: [PATCH 199/213] 8357079: Fix Windows AArch64 DevKit Creation Reviewed-by: erikj, ihse --- make/devkit/createWindowsDevkit.sh | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/make/devkit/createWindowsDevkit.sh b/make/devkit/createWindowsDevkit.sh index 757fb157ad4..7c55605c776 100644 --- a/make/devkit/createWindowsDevkit.sh +++ b/make/devkit/createWindowsDevkit.sh @@ -64,6 +64,30 @@ IS_WSL=`echo $UNAME_RELEASE | grep Microsoft` IS_MSYS=`echo $UNAME_OS | grep -i Msys` MSYS2_ARG_CONV_EXCL="*" # make "cmd.exe /c" work for msys2 CMD_EXE="cmd.exe /c" + +# Detect host architecture to determine devkit platform support +# Note: The devkit always includes x86, x64, and aarch64 libraries and tools +# The difference is in toolchain capabilities: +# - On x64|AMD64 hosts: aarch64 tools are cross-compilation tools (Hostx64/arm64) +# - On aarch64|ARMv8 hosts: aarch64 tools are native tools (Hostarm64/arm64) +HOST_ARCH=`echo $PROCESSOR_IDENTIFIER` +case $HOST_ARCH in + AMD64) + echo "Running on x64 host - generating devkit with native x86/x64 tools and cross-compiled aarch64 tools." + echo "For native aarch64 compilation tools, run this script on a Windows/aarch64 machine." + SUPPORTED_PLATFORMS="x86, x64 (native) and aarch64 (cross-compiled)" + ;; + ARMv8) + echo "Running on aarch64 host - generating devkit with native tools for all platforms (x86, x64, aarch64)." + SUPPORTED_PLATFORMS="x86, x64, and aarch64 (all native)" + ;; + *) + echo "Unknown host architecture: $HOST_ARCH" + echo "Proceeding with devkit generation - toolchain capabilities may vary." + SUPPORTED_PLATFORMS="x86, x64, and aarch64" + ;; +esac + if test "x$IS_CYGWIN" != "x"; then BUILD_ENV="cygwin" elif test "x$IS_MSYS" != "x"; then @@ -139,6 +163,7 @@ DEVKIT_ROOT="${BUILD_DIR}/VS${VS_VERSION}-${VS_VERSION_SP}-devkit" DEVKIT_BUNDLE="${DEVKIT_ROOT}.tar.gz" echo "Creating devkit in $DEVKIT_ROOT" +echo "Platform support: $SUPPORTED_PLATFORMS" MSVCR_DLL=${MSVC_CRT_DIR}/vcruntime${VS_DLL_VERSION}.dll VCRUNTIME_1_DLL=${MSVC_CRT_DIR}/vcruntime${VS_DLL_VERSION}_1.dll @@ -156,7 +181,11 @@ REDIST_SUBDIR="VC/Redist/MSVC/$REDIST_VERSION" echo "Copying VC..." rm -rf $DEVKIT_ROOT/VC mkdir -p $DEVKIT_ROOT/VC/bin -cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/arm64" $DEVKIT_ROOT/VC/bin/ +if [ -d "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostarm64/arm64" ]; then + cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostarm64/arm64" $DEVKIT_ROOT/VC/bin/ +else + cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/arm64" $DEVKIT_ROOT/VC/bin/ +fi cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx64/x64" $DEVKIT_ROOT/VC/bin/ cp -r "$VS_INSTALL_DIR/${VC_SUBDIR}/bin/Hostx86/x86" $DEVKIT_ROOT/VC/bin/ mkdir -p $DEVKIT_ROOT/VC/lib From 01b15bc1f961f43ae11db0c15f45763c4ec4180b Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 27 Jun 2025 06:43:50 +0000 Subject: [PATCH 200/213] 8360518: Docker tests do not work when asan is configured Reviewed-by: sgehwolf --- test/hotspot/jtreg/containers/docker/DockerBasicTest.java | 1 + test/hotspot/jtreg/containers/docker/ShareTmpDir.java | 1 + test/hotspot/jtreg/containers/docker/TestCPUAwareness.java | 1 + test/hotspot/jtreg/containers/docker/TestCPUSets.java | 1 + test/hotspot/jtreg/containers/docker/TestContainerInfo.java | 1 + test/hotspot/jtreg/containers/docker/TestJFREvents.java | 1 + test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java | 1 + test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java | 1 + test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java | 1 + test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java | 1 + test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java | 1 + .../hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java | 1 + test/hotspot/jtreg/containers/docker/TestMisc.java | 1 + test/hotspot/jtreg/containers/docker/TestPids.java | 1 + test/jdk/jdk/internal/platform/docker/TestDockerBasic.java | 1 + test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java | 1 + .../jdk/internal/platform/docker/TestDockerMemoryMetrics.java | 1 + .../platform/docker/TestDockerMemoryMetricsSubgroup.java | 1 + .../jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java | 1 + test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java | 1 + test/jdk/jdk/internal/platform/docker/TestPidsLimit.java | 1 + test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java | 1 + .../jdk/internal/platform/docker/TestUseContainerSupport.java | 1 + 23 files changed, 23 insertions(+) diff --git a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java index 9233b199532..8e2c0b6a85a 100644 --- a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java +++ b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java @@ -26,6 +26,7 @@ * @test * @summary Basic (sanity) test for JDK-under-test inside a docker image. * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java index 43cd6ec5152..9a4748563bd 100644 --- a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java +++ b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java @@ -28,6 +28,7 @@ * @key cgroups * @summary Test for hsperfdata file name conflict when two containers share the same /tmp directory * @requires container.support + * @requires !vm.asan * @library /test/lib * @build WaitForFlagFile * @run driver ShareTmpDir diff --git a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java index c51bfa1abbb..99220201f66 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java @@ -27,6 +27,7 @@ * @key cgroups * @summary Test JVM's CPU resource awareness when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.base/jdk.internal.platform diff --git a/test/hotspot/jtreg/containers/docker/TestCPUSets.java b/test/hotspot/jtreg/containers/docker/TestCPUSets.java index aabe82e131f..7894172e401 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUSets.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUSets.java @@ -27,6 +27,7 @@ * @key cgroups * @summary Test JVM's awareness of cpu sets (cpus and mems) * @requires container.support + * @requires !vm.asan * @requires (os.arch != "s390x") * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java index 5db3c2af098..b9b6fb65b75 100644 --- a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java +++ b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java @@ -28,6 +28,7 @@ * @summary Test container info for cgroup v2 * @key cgroups * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestJFREvents.java b/test/hotspot/jtreg/containers/docker/TestJFREvents.java index 77c735cde00..c8905f4e49c 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFREvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFREvents.java @@ -30,6 +30,7 @@ * Also make sure that PIDs are based on value provided by container, * not by the host system. * @requires (container.support & os.maxMemory >= 2g) + * @requires !vm.asan * @modules java.base/jdk.internal.platform * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java index 9f9497d9c63..c0dde368d1e 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRNetworkEvents.java @@ -28,6 +28,7 @@ * the reported host ip and host name are correctly reported within * the container. * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java index b7517254281..a9de46e00b0 100644 --- a/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java +++ b/test/hotspot/jtreg/containers/docker/TestJFRWithJMX.java @@ -26,6 +26,7 @@ * @test * @summary Test JFR recording controlled via JMX across container boundary. * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java index 9feeda6f4ad..91a07012f00 100644 --- a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java +++ b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java @@ -31,6 +31,7 @@ * namespace such as PID namespace, specific sub-directories, IPC and more. * @requires container.support * @requires vm.flagless + * @requires !vm.asan * @modules java.base/jdk.internal.misc * java.management * jdk.jartool/sun.tools.jar diff --git a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java index 14227a71068..7b05669085c 100644 --- a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java +++ b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java @@ -30,6 +30,7 @@ * @key cgroups * @summary Test container limits updating as they get updated at runtime without restart * @requires container.support + * @requires !vm.asan * @library /test/lib * @build jdk.test.whitebox.WhiteBox LimitUpdateChecker * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar whitebox.jar jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java index f8c8b34135d..f80a83842c9 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithCgroupV1.java @@ -32,6 +32,7 @@ * @test * @key cgroups * @requires os.family == "linux" + * @requires !vm.asan * @modules java.base/jdk.internal.platform * @library /test/lib * @build jdk.test.whitebox.WhiteBox PrintContainerInfo CheckOperatingSystemMXBean diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java index a75f314b53d..bd1713e578c 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryWithSubgroups.java @@ -36,6 +36,7 @@ * @test * @bug 8343191 * @requires os.family == "linux" + * @requires !vm.asan * @modules java.base/jdk.internal.platform * @library /test/lib * @build jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index 1ca3540683c..a1998cef344 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -26,6 +26,7 @@ * @test * @summary Test miscellanous functionality related to JVM running in docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/hotspot/jtreg/containers/docker/TestPids.java b/test/hotspot/jtreg/containers/docker/TestPids.java index 9b65a1b1ee8..2e9c97110b2 100644 --- a/test/hotspot/jtreg/containers/docker/TestPids.java +++ b/test/hotspot/jtreg/containers/docker/TestPids.java @@ -28,6 +28,7 @@ * @key cgroups * @summary Test JVM's awareness of pids controller * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.misc * java.management diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java index e236292de98..9a531d692ed 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerBasic.java @@ -28,6 +28,7 @@ * @summary Verify that -XshowSettings:system works * @key cgroups * @requires container.support + * @requires !vm.asan * @library /test/lib * @run main/timeout=360 TestDockerBasic */ diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java index 4d452f20eef..ff039913b8f 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerCpuMetrics.java @@ -35,6 +35,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsCpuTester diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java index e8dc616b5e7..7cbab5c3b86 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java @@ -33,6 +33,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsMemoryTester diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java index c6b94370807..0587d5a6bfb 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetricsSubgroup.java @@ -40,6 +40,7 @@ * @key cgroups * @summary Cgroup v1 subsystem fails to set subsystem path * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build MetricsMemoryTester diff --git a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java index 204d7a215d8..8e3d0cacd57 100644 --- a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java @@ -27,6 +27,7 @@ * @key cgroups * @bug 8242480 * @requires container.support + * @requires !vm.asan * @library /test/lib * @build GetFreeSwapSpaceSize * @run driver TestGetFreeSwapSpaceSize diff --git a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java index 1544088f688..31e90e8802a 100644 --- a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java +++ b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java @@ -30,6 +30,7 @@ * @key cgroups * @summary Test container limits updating as they get updated at runtime without restart * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build LimitUpdateChecker diff --git a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java index 9fedeb55234..6b19bb475f1 100644 --- a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java +++ b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java @@ -28,6 +28,7 @@ * @summary Test JDK Metrics class when running inside a docker container with limited pids * @bug 8266490 * @requires container.support + * @requires !vm.asan * @library /test/lib * @build TestPidsLimit * @run driver TestPidsLimit diff --git a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java index 93efff64cc4..49ec5663478 100644 --- a/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestSystemMetrics.java @@ -26,6 +26,7 @@ * @key cgroups * @summary Test JDK Metrics class when running inside docker container * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @run main TestSystemMetrics diff --git a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java index 6a96514771c..d8d300401a0 100644 --- a/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java +++ b/test/jdk/jdk/internal/platform/docker/TestUseContainerSupport.java @@ -26,6 +26,7 @@ * @test * @summary UseContainerSupport flag should reflect Metrics being available * @requires container.support + * @requires !vm.asan * @library /test/lib * @modules java.base/jdk.internal.platform * @build CheckUseContainerSupport From 97ec9d3e0a6e3455579b567e1f58026f5b168c09 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 27 Jun 2025 07:37:44 +0000 Subject: [PATCH 201/213] 8360533: ContainerRuntimeVersionTestUtils fromVersionString fails with some docker versions Reviewed-by: lucy, mdoerr, dholmes --- .../docker/ContainerRuntimeVersionTestUtils.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java b/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java index 88538e7e780..0d1c3a358ab 100644 --- a/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/ContainerRuntimeVersionTestUtils.java @@ -79,12 +79,21 @@ public static ContainerRuntimeVersionTestUtils fromVersionString(String version) try { // Example 'docker version 20.10.0 or podman version 4.9.4-rhel' String versNums = version.split("\\s+", 3)[2]; + // On some docker implementations e.g. RHEL8 ppc64le we have the following version output: + // Docker version v25.0.3, build 4debf41 + // Trim potentially leading 'v' and trailing ',' + if (versNums.startsWith("v")) { + versNums = versNums.substring(1); + } + int cidx = versNums.indexOf(','); + versNums = (cidx != -1) ? versNums.substring(0, cidx) : versNums; + String[] numbers = versNums.split("-")[0].split("\\.", 3); return new ContainerRuntimeVersionTestUtils(Integer.parseInt(numbers[0]), Integer.parseInt(numbers[1]), Integer.parseInt(numbers[2])); } catch (Exception e) { - throw new RuntimeException("Failed to parse container runtime version: " + version); + throw new RuntimeException("Failed to parse container runtime version: " + version, e); } } @@ -104,4 +113,4 @@ public static String getContainerRuntimeVersionStr() { public static ContainerRuntimeVersionTestUtils getContainerRuntimeVersion() { return ContainerRuntimeVersionTestUtils.fromVersionString(getContainerRuntimeVersionStr()); } -} \ No newline at end of file +} From 20e983a97c66902c61ee2fa1959a7e612266732b Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Fri, 27 Jun 2025 07:53:49 +0000 Subject: [PATCH 202/213] 8360487: Remove unnecessary List.indexOf key from AbstractMidiDevice.TransmitterList.remove Reviewed-by: azvegint, serb, aivanov --- .../classes/com/sun/media/sound/AbstractMidiDevice.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java b/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java index d8a404f500e..0cd5591b7c0 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/AbstractMidiDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -561,10 +561,7 @@ private void add(Transmitter t) { private void remove(Transmitter t) { synchronized(transmitters) { - int index = transmitters.indexOf(t); - if (index >= 0) { - transmitters.remove(index); - } + transmitters.remove(t); } } From aa26cede635011f5cc075cd528934ce8d8e8eef9 Mon Sep 17 00:00:00 2001 From: Qizheng Xing Date: Fri, 27 Jun 2025 08:17:13 +0000 Subject: [PATCH 203/213] 8360474: Add missing include guards for some HotSpot headers Reviewed-by: mhaessig, stefank, dholmes --- src/hotspot/os/aix/decoder_aix.hpp | 6 +++++- src/hotspot/share/gc/g1/g1SharedClosures.hpp | 7 ++++++- src/hotspot/share/opto/library_call.hpp | 4 ++++ src/hotspot/share/utilities/packedTable.hpp | 5 +++++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/hotspot/os/aix/decoder_aix.hpp b/src/hotspot/os/aix/decoder_aix.hpp index 0d87ba87b94..2ba3e1c5a3a 100644 --- a/src/hotspot/os/aix/decoder_aix.hpp +++ b/src/hotspot/os/aix/decoder_aix.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -23,6 +23,9 @@ * */ +#ifndef OS_AIX_DECODER_AIX_HPP +#define OS_AIX_DECODER_AIX_HPP + #include "utilities/decoder.hpp" #include "porting_aix.hpp" @@ -44,3 +47,4 @@ class AIXDecoder: public AbstractDecoder { }; +#endif // OS_AIX_DECODER_AIX_HPP diff --git a/src/hotspot/share/gc/g1/g1SharedClosures.hpp b/src/hotspot/share/gc/g1/g1SharedClosures.hpp index 5541d6274a3..a81f62ff308 100644 --- a/src/hotspot/share/gc/g1/g1SharedClosures.hpp +++ b/src/hotspot/share/gc/g1/g1SharedClosures.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,9 @@ * */ +#ifndef SHARE_GC_G1_G1SHAREDCLOSURES_HPP +#define SHARE_GC_G1_G1SHAREDCLOSURES_HPP + #include "gc/g1/g1NMethodClosure.hpp" #include "gc/g1/g1OopClosures.hpp" #include "memory/iterator.hpp" @@ -54,3 +57,5 @@ class G1SharedClosures { _clds(&_oops_in_cld, process_only_dirty), _nmethods(pss->worker_id(), &_oops_in_nmethod, should_mark) {} }; + +#endif // SHARE_GC_G1_G1SHAREDCLOSURES_HPP diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index a622eefa248..94b02290ccd 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -22,6 +22,9 @@ * */ +#ifndef SHARE_OPTO_LIBRARY_CALL_HPP +#define SHARE_OPTO_LIBRARY_CALL_HPP + #include "ci/ciMethod.hpp" #include "classfile/javaClasses.hpp" #include "opto/callGenerator.hpp" @@ -416,3 +419,4 @@ class LibraryCallKit : public GraphKit { bool inline_blackhole(); }; +#endif // SHARE_OPTO_LIBRARY_CALL_HPP diff --git a/src/hotspot/share/utilities/packedTable.hpp b/src/hotspot/share/utilities/packedTable.hpp index ed08a2b4c21..1266c65cbf1 100644 --- a/src/hotspot/share/utilities/packedTable.hpp +++ b/src/hotspot/share/utilities/packedTable.hpp @@ -22,6 +22,9 @@ * */ +#ifndef SHARE_UTILITIES_PACKEDTABLE_HPP +#define SHARE_UTILITIES_PACKEDTABLE_HPP + #include "oops/array.hpp" #include "utilities/globalDefinitions.hpp" @@ -121,3 +124,5 @@ class PackedTableLookup: public PackedTableBase { } } }; + +#endif // SHARE_UTILITIES_PACKEDTABLE_HPP From d8f9b188fa488c9c6e343c62a148cfe9fc8a563b Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 27 Jun 2025 11:20:49 +0000 Subject: [PATCH 204/213] 8268406: Deallocate jmethodID native memory Reviewed-by: dholmes, sspitsyn, dcubed, eosterlund, aboldtch --- .../share/classfile/classLoaderData.cpp | 45 ++-- .../share/classfile/classLoaderData.hpp | 15 +- src/hotspot/share/memory/universe.cpp | 5 +- src/hotspot/share/nmt/memTag.hpp | 3 +- src/hotspot/share/oops/instanceKlass.cpp | 84 ++++--- src/hotspot/share/oops/instanceKlass.hpp | 12 +- .../share/oops/instanceKlass.inline.hpp | 10 +- src/hotspot/share/oops/jmethodIDTable.cpp | 194 +++++++++++++++ src/hotspot/share/oops/jmethodIDTable.hpp | 55 +++++ src/hotspot/share/oops/method.cpp | 223 +++--------------- src/hotspot/share/oops/method.hpp | 15 +- src/hotspot/share/prims/jniCheck.cpp | 2 +- src/hotspot/share/prims/jvmtiEnv.cpp | 20 +- .../share/prims/jvmtiRedefineClasses.cpp | 7 + src/hotspot/share/runtime/mutexLocker.cpp | 2 +- .../gtest/oops/test_jmethodIDTable.cpp | 59 +++++ 16 files changed, 456 insertions(+), 295 deletions(-) create mode 100644 src/hotspot/share/oops/jmethodIDTable.cpp create mode 100644 src/hotspot/share/oops/jmethodIDTable.hpp create mode 100644 test/hotspot/gtest/oops/test_jmethodIDTable.cpp diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp index 825072cb13b..d6677faa91d 100644 --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -65,6 +65,7 @@ #include "memory/resourceArea.hpp" #include "memory/universe.hpp" #include "oops/access.inline.hpp" +#include "oops/jmethodIDTable.hpp" #include "oops/klass.inline.hpp" #include "oops/oop.inline.hpp" #include "oops/oopHandle.inline.hpp" @@ -578,6 +579,33 @@ void ClassLoaderData::remove_class(Klass* scratch_class) { ShouldNotReachHere(); // should have found this class!! } +void ClassLoaderData::add_jmethod_id(jmethodID mid) { + MutexLocker m1(metaspace_lock(), Mutex::_no_safepoint_check_flag); + if (_jmethod_ids == nullptr) { + _jmethod_ids = new (mtClass) GrowableArray(32, mtClass); + } + _jmethod_ids->push(mid); +} + +// Method::remove_jmethod_ids removes jmethodID entries from the table which +// releases memory. +// Because native code (e.g., JVMTI agent) holding jmethod_ids may access them +// after the associated classes and class loader are unloaded, subsequent lookups +// for these ids will return null since they are no longer found in the table. +// The Java Native Interface Specification says "method ID +// does not prevent the VM from unloading the class from which the ID has +// been derived. After the class is unloaded, the method or field ID becomes +// invalid". +void ClassLoaderData::remove_jmethod_ids() { + MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); + for (int i = 0; i < _jmethod_ids->length(); i++) { + jmethodID mid = _jmethod_ids->at(i); + JmethodIDTable::remove(mid); + } + delete _jmethod_ids; + _jmethod_ids = nullptr; +} + void ClassLoaderData::unload() { _unloading = true; @@ -599,19 +627,8 @@ void ClassLoaderData::unload() { // after erroneous classes are released. classes_do(InstanceKlass::unload_class); - // Method::clear_jmethod_ids only sets the jmethod_ids to null without - // releasing the memory for related JNIMethodBlocks and JNIMethodBlockNodes. - // This is done intentionally because native code (e.g. JVMTI agent) holding - // jmethod_ids may access them after the associated classes and class loader - // are unloaded. The Java Native Interface Specification says "method ID - // does not prevent the VM from unloading the class from which the ID has - // been derived. After the class is unloaded, the method or field ID becomes - // invalid". In real world usages, the native code may rely on jmethod_ids - // being null after class unloading. Hence, it is unsafe to free the memory - // from the VM side without knowing when native code is going to stop using - // them. if (_jmethod_ids != nullptr) { - Method::clear_jmethod_ids(this); + remove_jmethod_ids(); } } @@ -1037,9 +1054,7 @@ void ClassLoaderData::print_on(outputStream* out) const { out->print_cr(" - dictionary " INTPTR_FORMAT, p2i(_dictionary)); } if (_jmethod_ids != nullptr) { - out->print (" - jmethod count "); - Method::print_jmethod_ids_count(this, out); - out->print_cr(""); + out->print_cr(" - jmethod count %d", _jmethod_ids->length()); } out->print_cr(" - deallocate list " INTPTR_FORMAT, p2i(_deallocate_list)); out->print_cr(" - next CLD " INTPTR_FORMAT, p2i(_next)); diff --git a/src/hotspot/share/classfile/classLoaderData.hpp b/src/hotspot/share/classfile/classLoaderData.hpp index 19dbb0b1b36..e6302888283 100644 --- a/src/hotspot/share/classfile/classLoaderData.hpp +++ b/src/hotspot/share/classfile/classLoaderData.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,7 +53,6 @@ // and provides iterators for root tracing and other GC operations. class ClassLoaderDataGraph; -class JNIMethodBlock; class ModuleEntry; class PackageEntry; class ModuleEntryTable; @@ -143,10 +142,9 @@ class ClassLoaderData : public CHeapObj { ModuleEntry* _unnamed_module; // This class loader's unnamed module. Dictionary* _dictionary; // The loaded InstanceKlasses, including initiated by this class loader - // These method IDs are created for the class loader and set to null when the - // class loader is unloaded. They are rarely freed, only for redefine classes - // and if they lose a data race in InstanceKlass. - JNIMethodBlock* _jmethod_ids; + // These method IDs are created for the class loader and removed when the + // class loader is unloaded. + GrowableArray* _jmethod_ids; // Metadata to be deallocated when it's safe at class unloading, when // this class loader isn't unloaded itself. @@ -316,8 +314,9 @@ class ClassLoaderData : public CHeapObj { void classes_do(KlassClosure* klass_closure); Klass* klasses() { return _klasses; } - JNIMethodBlock* jmethod_ids() const { return _jmethod_ids; } - void set_jmethod_ids(JNIMethodBlock* new_block) { _jmethod_ids = new_block; } + void add_jmethod_id(jmethodID id); + void remove_jmethod_ids(); + GrowableArray* jmethod_ids() const { return _jmethod_ids; } void print() const; void print_on(outputStream* out) const PRODUCT_RETURN; diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index ffdeec06ef8..100ed9b42dd 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -60,6 +60,7 @@ #include "oops/compressedOops.hpp" #include "oops/instanceKlass.hpp" #include "oops/instanceMirrorKlass.hpp" +#include "oops/jmethodIDTable.hpp" #include "oops/klass.inline.hpp" #include "oops/objArrayOop.inline.hpp" #include "oops/objLayout.hpp" @@ -436,6 +437,9 @@ void Universe::genesis(TRAPS) { vmSymbols::initialize(); + // Initialize table for matching jmethodID, before SystemDictionary. + JmethodIDTable::initialize(); + SystemDictionary::initialize(CHECK); // Create string constants @@ -444,7 +448,6 @@ void Universe::genesis(TRAPS) { s = StringTable::intern("-2147483648", CHECK); _the_min_jint_string = OopHandle(vm_global(), s); - #if INCLUDE_CDS if (CDSConfig::is_using_archive()) { // Verify shared interfaces array. diff --git a/src/hotspot/share/nmt/memTag.hpp b/src/hotspot/share/nmt/memTag.hpp index 9255645638d..b1b59c9151a 100644 --- a/src/hotspot/share/nmt/memTag.hpp +++ b/src/hotspot/share/nmt/memTag.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,7 @@ f(mtMetaspace, "Metaspace") \ f(mtStringDedup, "String Deduplication") \ f(mtObjectMonitor, "Object Monitors") \ + f(mtJNI, "JNI") \ f(mtNone, "Unknown") \ //end diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 07b002f944e..f4ab8c31409 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -2395,13 +2395,26 @@ jmethodID InstanceKlass::update_jmethod_id(jmethodID* jmeths, Method* method, in return new_id; } +// Allocate the jmethodID cache. +static jmethodID* create_jmethod_id_cache(size_t size) { + jmethodID* jmeths = NEW_C_HEAP_ARRAY(jmethodID, size + 1, mtClass); + memset(jmeths, 0, (size + 1) * sizeof(jmethodID)); + // cache size is stored in element[0], other elements offset by one + jmeths[0] = (jmethodID)size; + return jmeths; +} + +// When reading outside a lock, use this. +jmethodID* InstanceKlass::methods_jmethod_ids_acquire() const { + return Atomic::load_acquire(&_methods_jmethod_ids); +} + +void InstanceKlass::release_set_methods_jmethod_ids(jmethodID* jmeths) { + Atomic::release_store(&_methods_jmethod_ids, jmeths); +} + // Lookup or create a jmethodID. -// This code is called by the VMThread and JavaThreads so the -// locking has to be done very carefully to avoid deadlocks -// and/or other cache consistency problems. -// -jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) { - Method* method = method_h(); +jmethodID InstanceKlass::get_jmethod_id(Method* method) { int idnum = method->method_idnum(); jmethodID* jmeths = methods_jmethod_ids_acquire(); @@ -2422,15 +2435,12 @@ jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) { if (jmeths == nullptr) { MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); - jmeths = methods_jmethod_ids_acquire(); + jmeths = _methods_jmethod_ids; // Still null? if (jmeths == nullptr) { size_t size = idnum_allocated_count(); assert(size > (size_t)idnum, "should already have space"); - jmeths = NEW_C_HEAP_ARRAY(jmethodID, size + 1, mtClass); - memset(jmeths, 0, (size + 1) * sizeof(jmethodID)); - // cache size is stored in element[0], other elements offset by one - jmeths[0] = (jmethodID)size; + jmeths = create_jmethod_id_cache(size); jmethodID new_id = update_jmethod_id(jmeths, method, idnum); // publish jmeths @@ -2460,10 +2470,7 @@ void InstanceKlass::update_methods_jmethod_cache() { if (old_size < size + 1) { // Allocate a larger one and copy entries to the new one. // They've already been updated to point to new methods where applicable (i.e., not obsolete). - jmethodID* new_cache = NEW_C_HEAP_ARRAY(jmethodID, size + 1, mtClass); - memset(new_cache, 0, (size + 1) * sizeof(jmethodID)); - // The cache size is stored in element[0]; the other elements are offset by one. - new_cache[0] = (jmethodID)size; + jmethodID* new_cache = create_jmethod_id_cache(size); for (int i = 1; i <= (int)old_size; i++) { new_cache[i] = cache[i]; @@ -2474,24 +2481,30 @@ void InstanceKlass::update_methods_jmethod_cache() { } } -// Figure out how many jmethodIDs haven't been allocated, and make -// sure space for them is pre-allocated. This makes getting all -// method ids much, much faster with classes with more than 8 +// Make a jmethodID for all methods in this class. This makes getting all method +// ids much, much faster with classes with more than 8 // methods, and has a *substantial* effect on performance with jvmti // code that loads all jmethodIDs for all classes. -void InstanceKlass::ensure_space_for_methodids(int start_offset) { - int new_jmeths = 0; +void InstanceKlass::make_methods_jmethod_ids() { + MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); + jmethodID* jmeths = _methods_jmethod_ids; + if (jmeths == nullptr) { + jmeths = create_jmethod_id_cache(idnum_allocated_count()); + release_set_methods_jmethod_ids(jmeths); + } + int length = methods()->length(); - for (int index = start_offset; index < length; index++) { + for (int index = 0; index < length; index++) { Method* m = methods()->at(index); - jmethodID id = m->find_jmethod_id_or_null(); - if (id == nullptr) { - new_jmeths++; + int idnum = m->method_idnum(); + assert(!m->is_old(), "should not have old methods or I'm confused"); + jmethodID id = Atomic::load_acquire(&jmeths[idnum + 1]); + if (!m->is_overpass() && // skip overpasses + id == nullptr) { + id = Method::make_jmethod_id(class_loader_data(), m); + Atomic::release_store(&jmeths[idnum + 1], id); } } - if (new_jmeths != 0) { - Method::ensure_jmethod_ids(class_loader_data(), new_jmeths); - } } // Lookup a jmethodID, null if not found. Do no blocking, no allocations, no handles @@ -2923,7 +2936,7 @@ void InstanceKlass::release_C_heap_structures(bool release_sub_metadata) { JNIid::deallocate(jni_ids()); set_jni_ids(nullptr); - jmethodID* jmeths = methods_jmethod_ids_acquire(); + jmethodID* jmeths = _methods_jmethod_ids; if (jmeths != nullptr) { release_set_methods_jmethod_ids(nullptr); FreeHeap(jmeths); @@ -4275,17 +4288,14 @@ bool InstanceKlass::should_clean_previous_versions_and_reset() { return ret; } -// This nulls out jmethodIDs for all methods in 'klass' -// It needs to be called explicitly for all previous versions of a class because these may not be cleaned up -// during class unloading. -// We can not use the jmethodID cache associated with klass directly because the 'previous' versions -// do not have the jmethodID cache filled in. Instead, we need to lookup jmethodID for each method and this -// is expensive - O(n) for one jmethodID lookup. For all contained methods it is O(n^2). -// The reason for expensive jmethodID lookup for each method is that there is no direct link between method and jmethodID. -void InstanceKlass::clear_jmethod_ids(InstanceKlass* klass) { +// This nulls out the jmethodID for all obsolete methods in the previous version of the 'klass'. +// These obsolete methods only exist in the previous version and we're about to delete the memory for them. +// The jmethodID for these are deallocated when we unload the class, so this doesn't remove them from the table. +void InstanceKlass::clear_obsolete_jmethod_ids(InstanceKlass* klass) { Array* method_refs = klass->methods(); for (int k = 0; k < method_refs->length(); k++) { Method* method = method_refs->at(k); + // Only need to clear obsolete methods. if (method != nullptr && method->is_obsolete()) { method->clear_jmethod_id(); } @@ -4335,7 +4345,7 @@ void InstanceKlass::purge_previous_version_list() { // Unlink from previous version list. assert(pv_node->class_loader_data() == loader_data, "wrong loader_data"); InstanceKlass* next = pv_node->previous_versions(); - clear_jmethod_ids(pv_node); // jmethodID maintenance for the unloaded class + clear_obsolete_jmethod_ids(pv_node); // jmethodID maintenance for the unloaded class pv_node->link_previous_versions(nullptr); // point next to null last->link_previous_versions(next); // Delete this node directly. Nothing is referring to it and we don't diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 55ab0996a4a..2512d8d869d 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -781,8 +781,8 @@ class InstanceKlass: public Klass { u2 method_index); // jmethodID support - jmethodID get_jmethod_id(const methodHandle& method_h); - void ensure_space_for_methodids(int start_offset = 0); + jmethodID get_jmethod_id(Method* method); + void make_methods_jmethod_ids(); jmethodID jmethod_id_or_null(Method* method); void update_methods_jmethod_cache(); @@ -1056,10 +1056,10 @@ class InstanceKlass: public Klass { Atomic::store(&_init_thread, thread); } - inline jmethodID* methods_jmethod_ids_acquire() const; - inline void release_set_methods_jmethod_ids(jmethodID* jmeths); - // This nulls out jmethodIDs for all methods in 'klass' - static void clear_jmethod_ids(InstanceKlass* klass); + jmethodID* methods_jmethod_ids_acquire() const; + void release_set_methods_jmethod_ids(jmethodID* jmeths); + // This nulls out obsolete jmethodIDs for all methods in 'klass'. + static void clear_obsolete_jmethod_ids(InstanceKlass* klass); jmethodID update_jmethod_id(jmethodID* jmeths, Method* method, int idnum); public: diff --git a/src/hotspot/share/oops/instanceKlass.inline.hpp b/src/hotspot/share/oops/instanceKlass.inline.hpp index 1b4664f5a4b..f9db34f4884 100644 --- a/src/hotspot/share/oops/instanceKlass.inline.hpp +++ b/src/hotspot/share/oops/instanceKlass.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,14 +71,6 @@ inline void InstanceKlass::release_set_array_klasses(ObjArrayKlass* k) { Atomic::release_store(&_array_klasses, k); } -inline jmethodID* InstanceKlass::methods_jmethod_ids_acquire() const { - return Atomic::load_acquire(&_methods_jmethod_ids); -} - -inline void InstanceKlass::release_set_methods_jmethod_ids(jmethodID* jmeths) { - Atomic::release_store(&_methods_jmethod_ids, jmeths); -} - // The iteration over the oops in objects is a hot path in the GC code. // By force inlining the following functions, we get similar GC performance // as the previous macro based implementation. diff --git a/src/hotspot/share/oops/jmethodIDTable.cpp b/src/hotspot/share/oops/jmethodIDTable.cpp new file mode 100644 index 00000000000..9dba79229e7 --- /dev/null +++ b/src/hotspot/share/oops/jmethodIDTable.cpp @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "logging/log.hpp" +#include "memory/allocation.hpp" +#include "memory/resourceArea.hpp" +#include "oops/jmethodIDTable.hpp" +#include "oops/method.hpp" +#include "runtime/mutexLocker.hpp" +#include "utilities/concurrentHashTable.inline.hpp" +#include "utilities/concurrentHashTableTasks.inline.hpp" +#include "utilities/macros.hpp" + +// Save (jmethod, Method*) in a hashtable to lookup Method. +// The CHT is for performance because it has lock free lookup. +// The value of the next jmethodID. This only increments (always unique IDs). +static uint64_t _jmethodID_counter = 0; +// Tracks the number of jmethodID entries in the _jmethod_id_table. +// Incremented on insert, decremented on remove. Used to track if we need to resize the table. +static uint64_t _jmethodID_entry_count = 0; + +uint64_t JmethodIDTable::get_entry_count() { return _jmethodID_entry_count; } + +class JmethodEntry { + public: + uint64_t _id; + Method* _method; + + JmethodEntry(uint64_t id, Method* method) : _id(id), _method(method) {} +}; + +class JmethodIDTableConfig : public AllStatic { + public: + typedef JmethodEntry Value; + static void* allocate_node(void* context, size_t size, Value const& value) { + return AllocateHeap(size, mtJNI); + } + static void free_node(void* context, void* memory, Value const& value) { + FreeHeap(memory); + } + static uintx get_hash(Value const& value, bool* is_dead) { + *is_dead = false; + return value._id; + } + static bool is_dead(Value const& value) { + return false; + } +}; + +using MethodIdTable = ConcurrentHashTable; +static MethodIdTable* _jmethod_id_table = nullptr; + +void JmethodIDTable::initialize() { + const size_t start_size = 10; + // 2^24 is max size + const size_t end_size = 24; + // If a chain gets to 32 something might be wrong. + const size_t grow_hint = 32; + + _jmethod_id_table = new MethodIdTable(start_size, end_size, grow_hint); +} + +class JmethodIDLookup : StackObj { + private: + uint64_t _mid; + + public: + JmethodIDLookup(const uint64_t mid) : _mid(mid) {} + uintx get_hash() const { + return _mid; + } + bool equals(JmethodEntry* value) { + return _mid == value->_id; + } + + bool is_dead(JmethodEntry* value) { + return false; + } +}; + +static JmethodEntry* get_jmethod_entry(jmethodID mid) { + assert(mid != nullptr, "JNI method id should not be null"); + + Thread* current = Thread::current(); + JmethodIDLookup lookup((uint64_t)mid); + JmethodEntry* result = nullptr; + auto get = [&] (JmethodEntry* value) { + // function called if value is found so is never null + result = value; + }; + bool needs_rehashing = false; + _jmethod_id_table->get(current, lookup, get, &needs_rehashing); + assert(!needs_rehashing, "should never need rehashing"); + return result; +} + +Method* JmethodIDTable::resolve_jmethod_id(jmethodID mid) { + JmethodEntry* result = get_jmethod_entry(mid); + return result == nullptr ? nullptr : result->_method; +} + +const unsigned _resize_load_trigger = 5; // load factor that will trigger the resize + +static unsigned table_size(Thread* current) { + return 1 << _jmethod_id_table->get_size_log2(current); +} + +static bool needs_resize(Thread* current) { + return ((_jmethodID_entry_count > (_resize_load_trigger * table_size(current))) && + !_jmethod_id_table->is_max_size_reached()); +} + +// Add a method id to the jmethod_ids. +jmethodID JmethodIDTable::make_jmethod_id(Method* m) { + bool grow_hint, clean_hint; + + assert_locked_or_safepoint(JmethodIdCreation_lock); + // Update jmethodID global counter. + _jmethodID_counter++; + + JmethodEntry new_entry(_jmethodID_counter, m); + Thread* current = Thread::current(); + JmethodIDLookup lookup(_jmethodID_counter); + bool created = _jmethod_id_table->insert(current, lookup, new_entry, &grow_hint, &clean_hint); + assert(created, "must be"); + log_debug(jmethod)("Inserted jmethod id " UINT64_FORMAT_X, _jmethodID_counter); + // Increment number of entries in the table. + _jmethodID_entry_count++; + + // Resize table if it needs to grow. The _jmethod_id_table has a good distribution. + if (needs_resize(current)) { + _jmethod_id_table->grow(current); + log_info(jmethod)("Growing table to %d for " UINT64_FORMAT " entries", table_size(current), _jmethodID_counter); + } + return (jmethodID)_jmethodID_counter; +} + +void JmethodIDTable::remove(jmethodID jmid) { + assert_locked_or_safepoint(JmethodIdCreation_lock); + JmethodIDLookup lookup((uint64_t)jmid); + Thread* current = Thread::current(); + JmethodEntry* result; + auto get = [&] (JmethodEntry* value) { + // The function that is called if value is found, so is never null. + result = value; + }; + bool removed = _jmethod_id_table->remove(current, lookup, get); + assert(removed, "must be"); + log_debug(jmethod)("Removed jmethod id " UINT64_FORMAT_X, (uint64_t)jmid); + // Decrement number of entries in the table. + _jmethodID_entry_count--; +} + +void JmethodIDTable::change_method_associated_with_jmethod_id(jmethodID jmid, Method* new_method) { + assert_locked_or_safepoint(JmethodIdCreation_lock); + JmethodEntry* result = get_jmethod_entry(jmid); + // Change table entry to point to the new method. + log_debug(jmethod)("Changed jmethod id " UINT64_FORMAT_X " from " PTR_FORMAT " to " PTR_FORMAT, (uint64_t)jmid, + p2i(result->_method), p2i(new_method)); + result->_method = new_method; +} + +void JmethodIDTable::clear_jmethod_id(jmethodID jmid, Method* obsolete_method) { + assert_locked_or_safepoint(JmethodIdCreation_lock); + JmethodEntry* result = get_jmethod_entry(jmid); + // We need to make sure that jmethodID actually resolves to this method + // - multiple redefined versions may share jmethodID slots and if a method + // has already been rewired to a newer version we could be clearing + // the reference to a still existing method instance. + if (result->_method == obsolete_method) { + result->_method = nullptr; + } +} diff --git a/src/hotspot/share/oops/jmethodIDTable.hpp b/src/hotspot/share/oops/jmethodIDTable.hpp new file mode 100644 index 00000000000..cdbe5c87855 --- /dev/null +++ b/src/hotspot/share/oops/jmethodIDTable.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_OOPS_JMETHODIDTABLE_HPP +#define SHARE_OOPS_JMETHODIDTABLE_HPP + +#include "jni.h" +#include "memory/allocation.hpp" + +// Class for associating Method with jmethodID +class Method; + +class JmethodIDTable : public AllStatic { + public: + static void initialize(); + + // Given a Method return a jmethodID. + static jmethodID make_jmethod_id(Method* m); + + // Given a jmethodID, return a Method. + static Method* resolve_jmethod_id(jmethodID mid); + + // Class unloading support, remove the associations from the tables. Stale jmethodID will + // not be found and return null. + static void remove(jmethodID mid); + + // RedefineClasses support + static void change_method_associated_with_jmethod_id(jmethodID jmid, Method* new_method); + static void clear_jmethod_id(jmethodID jmid, Method* m); + + static uint64_t get_entry_count(); +}; + +#endif // SHARE_OOPS_JMETHODIDTABLE_HPP diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index bb7a0576eec..7552bf50ed9 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -53,6 +53,7 @@ #include "nmt/memTracker.hpp" #include "oops/constMethod.hpp" #include "oops/constantPool.hpp" +#include "oops/jmethodIDTable.hpp" #include "oops/klass.inline.hpp" #include "oops/method.inline.hpp" #include "oops/methodData.hpp" @@ -2059,172 +2060,33 @@ void BreakpointInfo::clear(Method* method) { #endif // INCLUDE_JVMTI // jmethodID handling - -// This is a block allocating object, sort of like JNIHandleBlock, only a -// lot simpler. -// It's allocated on the CHeap because once we allocate a jmethodID, we can -// never get rid of it. - -static const int min_block_size = 8; - -class JNIMethodBlockNode : public CHeapObj { - friend class JNIMethodBlock; - Method** _methods; - int _number_of_methods; - int _top; - JNIMethodBlockNode* _next; - - public: - - JNIMethodBlockNode(int num_methods = min_block_size); - - ~JNIMethodBlockNode() { FREE_C_HEAP_ARRAY(Method*, _methods); } - - void ensure_methods(int num_addl_methods) { - if (_top < _number_of_methods) { - num_addl_methods -= _number_of_methods - _top; - if (num_addl_methods <= 0) { - return; - } - } - if (_next == nullptr) { - _next = new JNIMethodBlockNode(MAX2(num_addl_methods, min_block_size)); - } else { - _next->ensure_methods(num_addl_methods); - } - } -}; - -class JNIMethodBlock : public CHeapObj { - JNIMethodBlockNode _head; - JNIMethodBlockNode *_last_free; - public: - static Method* const _free_method; - - JNIMethodBlock(int initial_capacity = min_block_size) - : _head(initial_capacity), _last_free(&_head) {} - - void ensure_methods(int num_addl_methods) { - _last_free->ensure_methods(num_addl_methods); - } - - Method** add_method(Method* m) { - for (JNIMethodBlockNode* b = _last_free; b != nullptr; b = b->_next) { - if (b->_top < b->_number_of_methods) { - // top points to the next free entry. - int i = b->_top; - b->_methods[i] = m; - b->_top++; - _last_free = b; - return &(b->_methods[i]); - } else if (b->_top == b->_number_of_methods) { - // if the next free entry ran off the block see if there's a free entry - for (int i = 0; i < b->_number_of_methods; i++) { - if (b->_methods[i] == _free_method) { - b->_methods[i] = m; - _last_free = b; - return &(b->_methods[i]); - } - } - // Only check each block once for frees. They're very unlikely. - // Increment top past the end of the block. - b->_top++; - } - // need to allocate a next block. - if (b->_next == nullptr) { - b->_next = _last_free = new JNIMethodBlockNode(); - } - } - guarantee(false, "Should always allocate a free block"); - return nullptr; - } - - bool contains(Method** m) { - if (m == nullptr) return false; - for (JNIMethodBlockNode* b = &_head; b != nullptr; b = b->_next) { - if (b->_methods <= m && m < b->_methods + b->_number_of_methods) { - // This is a bit of extra checking, for two reasons. One is - // that contains() deals with pointers that are passed in by - // JNI code, so making sure that the pointer is aligned - // correctly is valuable. The other is that <= and > are - // technically not defined on pointers, so the if guard can - // pass spuriously; no modern compiler is likely to make that - // a problem, though (and if one did, the guard could also - // fail spuriously, which would be bad). - ptrdiff_t idx = m - b->_methods; - if (b->_methods + idx == m) { - return true; - } - } - } - return false; // not found - } - - // During class unloading the methods are cleared, which is different - // than freed. - void clear_all_methods() { - for (JNIMethodBlockNode* b = &_head; b != nullptr; b = b->_next) { - for (int i = 0; i< b->_number_of_methods; i++) { - b->_methods[i] = nullptr; - } - } - } -#ifndef PRODUCT - int count_methods() { - // count all allocated methods - int count = 0; - for (JNIMethodBlockNode* b = &_head; b != nullptr; b = b->_next) { - for (int i = 0; i< b->_number_of_methods; i++) { - if (b->_methods[i] != _free_method) count++; - } - } - return count; - } -#endif // PRODUCT -}; - -// Something that can't be mistaken for an address or a markWord -Method* const JNIMethodBlock::_free_method = (Method*)55; - -JNIMethodBlockNode::JNIMethodBlockNode(int num_methods) : _top(0), _next(nullptr) { - _number_of_methods = MAX2(num_methods, min_block_size); - _methods = NEW_C_HEAP_ARRAY(Method*, _number_of_methods, mtInternal); - for (int i = 0; i < _number_of_methods; i++) { - _methods[i] = JNIMethodBlock::_free_method; - } -} - -void Method::ensure_jmethod_ids(ClassLoaderData* cld, int capacity) { - // Have to add jmethod_ids() to class loader data thread-safely. - // Also have to add the method to the list safely, which the lock - // protects as well. - MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); - if (cld->jmethod_ids() == nullptr) { - cld->set_jmethod_ids(new JNIMethodBlock(capacity)); - } else { - cld->jmethod_ids()->ensure_methods(capacity); - } -} +// jmethodIDs are 64-bit integers that will never run out and are mapped in a table +// to their Method and vice versa. If JNI code has access to stale jmethodID, this +// wastes no memory but the Method* returned is null. // Add a method id to the jmethod_ids jmethodID Method::make_jmethod_id(ClassLoaderData* cld, Method* m) { // Have to add jmethod_ids() to class loader data thread-safely. - // Also have to add the method to the list safely, which the lock + // Also have to add the method to the InstanceKlass list safely, which the lock // protects as well. assert(JmethodIdCreation_lock->owned_by_self(), "sanity check"); + jmethodID jmid = JmethodIDTable::make_jmethod_id(m); + assert(jmid != nullptr, "must be created"); - ResourceMark rm; - log_debug(jmethod)("Creating jmethodID for Method %s", m->external_name()); - if (cld->jmethod_ids() == nullptr) { - cld->set_jmethod_ids(new JNIMethodBlock()); - } - // jmethodID is a pointer to Method* - return (jmethodID)cld->jmethod_ids()->add_method(m); + // Add to growable array in CLD. + cld->add_jmethod_id(jmid); + return jmid; } +// This looks in the InstanceKlass cache, then calls back to make_jmethod_id if not found. jmethodID Method::jmethod_id() { - methodHandle mh(Thread::current(), this); - return method_holder()->get_jmethod_id(mh); + return method_holder()->get_jmethod_id(this); +} + +// Get the Method out of the table given the method id. +Method* Method::resolve_jmethod_id(jmethodID mid) { + assert(mid != nullptr, "JNI method id should not be null"); + return JmethodIDTable::resolve_jmethod_id(mid); } void Method::change_method_associated_with_jmethod_id(jmethodID jmid, Method* new_method) { @@ -2232,25 +2094,34 @@ void Method::change_method_associated_with_jmethod_id(jmethodID jmid, Method* ne // scratch method holder. assert(resolve_jmethod_id(jmid)->method_holder()->class_loader() == new_method->method_holder()->class_loader() || - new_method->method_holder()->class_loader() == nullptr, // allow Unsafe substitution + new_method->method_holder()->class_loader() == nullptr, // allow substitution to Unsafe method "changing to a different class loader"); - // Just change the method in place, jmethodID pointer doesn't change. - *((Method**)jmid) = new_method; + JmethodIDTable::change_method_associated_with_jmethod_id(jmid, new_method); } -bool Method::is_method_id(jmethodID mid) { +// If there's a jmethodID for this method, clear the Method +// but leave jmethodID for this method in the table. +// It's deallocated with class unloading. +void Method::clear_jmethod_id() { + jmethodID mid = method_holder()->jmethod_id_or_null(this); + if (mid != nullptr) { + JmethodIDTable::clear_jmethod_id(mid, this); + } +} + +bool Method::validate_jmethod_id(jmethodID mid) { Method* m = resolve_jmethod_id(mid); assert(m != nullptr, "should be called with non-null method"); InstanceKlass* ik = m->method_holder(); ClassLoaderData* cld = ik->class_loader_data(); if (cld->jmethod_ids() == nullptr) return false; - return (cld->jmethod_ids()->contains((Method**)mid)); + return (cld->jmethod_ids()->contains(mid)); } Method* Method::checked_resolve_jmethod_id(jmethodID mid) { if (mid == nullptr) return nullptr; Method* o = resolve_jmethod_id(mid); - if (o == nullptr || o == JNIMethodBlock::_free_method) { + if (o == nullptr) { return nullptr; } // Method should otherwise be valid. Assert for testing. @@ -2259,7 +2130,7 @@ Method* Method::checked_resolve_jmethod_id(jmethodID mid) { // unloaded, we need to return null here too because after a safepoint, its memory // will be reclaimed. return o->method_holder()->is_loader_alive() ? o : nullptr; -}; +} void Method::set_on_stack(const bool value) { // Set both the method itself and its constant pool. The constant pool @@ -2280,25 +2151,6 @@ void Method::record_gc_epoch() { constants()->cache()->record_gc_epoch(); } -// Called when the class loader is unloaded to make all methods weak. -void Method::clear_jmethod_ids(ClassLoaderData* loader_data) { - loader_data->jmethod_ids()->clear_all_methods(); -} - -void Method::clear_jmethod_id() { - // Being at a safepoint prevents racing against other class redefinitions - assert(SafepointSynchronize::is_at_safepoint(), "should be at safepoint"); - // The jmethodID is not stored in the Method instance, we need to look it up first - jmethodID methodid = find_jmethod_id_or_null(); - // We need to make sure that jmethodID actually resolves to this method - // - multiple redefined versions may share jmethodID slots and if a method - // has already been rewired to a newer version we could be removing reference - // to a still existing method instance - if (methodid != nullptr && *((Method**)methodid) == this) { - *((Method**)methodid) = nullptr; - } -} - bool Method::has_method_vptr(const void* ptr) { Method m; // This assumes that the vtbl pointer is the first word of a C++ object. @@ -2323,13 +2175,6 @@ bool Method::is_valid_method(const Method* m) { } } -#ifndef PRODUCT -void Method::print_jmethod_ids_count(const ClassLoaderData* loader_data, outputStream* out) { - out->print("%d", loader_data->jmethod_ids()->count_methods()); -} -#endif // PRODUCT - - // Printing #ifndef PRODUCT diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index ce6b859f7c1..b241104b62c 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -704,18 +704,10 @@ class Method : public Metadata { // refers to null (as is the case for any weak reference). static jmethodID make_jmethod_id(ClassLoaderData* cld, Method* mh); - // Ensure there is enough capacity in the internal tracking data - // structures to hold the number of jmethodIDs you plan to generate. - // This saves substantial time doing allocations. - static void ensure_jmethod_ids(ClassLoaderData* cld, int capacity); - // Use resolve_jmethod_id() in situations where the caller is expected // to provide a valid jmethodID; the only sanity checks are in asserts; // result guaranteed not to be null. - inline static Method* resolve_jmethod_id(jmethodID mid) { - assert(mid != nullptr, "JNI method id should not be null"); - return *((Method**)mid); - } + static Method* resolve_jmethod_id(jmethodID mid); // Use checked_resolve_jmethod_id() in situations where the caller // should provide a valid jmethodID, but might not. Null is returned @@ -723,10 +715,9 @@ class Method : public Metadata { static Method* checked_resolve_jmethod_id(jmethodID mid); static void change_method_associated_with_jmethod_id(jmethodID old_jmid_ptr, Method* new_method); - static bool is_method_id(jmethodID mid); + static bool validate_jmethod_id(jmethodID mid); - // Clear methods - static void clear_jmethod_ids(ClassLoaderData* loader_data); + // Clear jmethodID void clear_jmethod_id(); static void print_jmethod_ids_count(const ClassLoaderData* loader_data, outputStream* out) PRODUCT_RETURN; diff --git a/src/hotspot/share/prims/jniCheck.cpp b/src/hotspot/share/prims/jniCheck.cpp index 14d9c36c9fd..fd0c5c330db 100644 --- a/src/hotspot/share/prims/jniCheck.cpp +++ b/src/hotspot/share/prims/jniCheck.cpp @@ -439,7 +439,7 @@ Method* jniCheck::validate_jmethod_id(JavaThread* thr, jmethodID method_id) { } // jmethodIDs are handles in the class loader data, // but that can be expensive so check it last - else if (!Method::is_method_id(method_id)) { + else if (!Method::validate_jmethod_id(method_id)) { ReportJNIFatalError(thr, fatal_non_weak_method); } return m; diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 6a1f451bb74..ad83f8c6d1b 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -2768,9 +2768,11 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth int result_length = ik->methods()->length(); jmethodID* result_list = (jmethodID*)jvmtiMalloc(result_length * sizeof(jmethodID)); int index; - bool jmethodids_found = true; int skipped = 0; // skip overpass methods + // Make jmethodIDs for all non-overpass methods. + ik->make_methods_jmethod_ids(); + for (index = 0; index < result_length; index++) { Method* m = ik->methods()->at(index); // Depending on can_maintain_original_method_order capability use the original @@ -2783,20 +2785,8 @@ JvmtiEnv::GetClassMethods(oop k_mirror, jint* method_count_ptr, jmethodID** meth skipped++; continue; } - jmethodID id; - if (jmethodids_found) { - id = m->find_jmethod_id_or_null(); - if (id == nullptr) { - // If we find an uninitialized value, make sure there is - // enough space for all the uninitialized values we might - // find. - ik->ensure_space_for_methodids(index); - jmethodids_found = false; - id = m->jmethod_id(); - } - } else { - id = m->jmethod_id(); - } + jmethodID id = m->find_jmethod_id_or_null(); + assert(id != nullptr, "should be created above"); result_list[result_index] = id; } diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index b7abacbe5b3..3066ef74cb8 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -3789,6 +3789,13 @@ void VM_RedefineClasses::AdjustAndCleanMetadata::do_klass(Klass* k) { void VM_RedefineClasses::update_jmethod_ids() { for (int j = 0; j < _matching_methods_length; ++j) { Method* old_method = _matching_old_methods[j]; + // The method_idnum should be within the range of 1..number-of-methods + // until incremented later for obsolete methods. + // The increment is so if a jmethodID is created for an old obsolete method + // it gets a new jmethodID cache slot in the InstanceKlass. + // They're cleaned out later when all methods of the previous version are purged. + assert(old_method->method_idnum() <= _old_methods->length(), + "shouldn't be incremented yet for obsolete methods"); jmethodID jmid = old_method->find_jmethod_id_or_null(); if (jmid != nullptr) { // There is a jmethodID, change it to point to the new method diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index b90f8c23a6d..0a6f472c8f0 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -236,7 +236,7 @@ void mutex_init() { MUTEX_DEFN(Service_lock , PaddedMonitor, service); // used for service thread operations MUTEX_DEFN(Notification_lock , PaddedMonitor, service); // used for notification thread operations - MUTEX_DEFN(JmethodIdCreation_lock , PaddedMutex , nosafepoint-2); // used for creating jmethodIDs. + MUTEX_DEFN(JmethodIdCreation_lock , PaddedMutex , nosafepoint-1); // used for creating jmethodIDs can also lock HandshakeState_lock MUTEX_DEFN(InvokeMethodTypeTable_lock , PaddedMutex , safepoint); MUTEX_DEFN(InvokeMethodIntrinsicTable_lock , PaddedMonitor, safepoint); MUTEX_DEFN(AdapterHandlerLibrary_lock , PaddedMutex , safepoint); diff --git a/test/hotspot/gtest/oops/test_jmethodIDTable.cpp b/test/hotspot/gtest/oops/test_jmethodIDTable.cpp new file mode 100644 index 00000000000..12ee939a9b1 --- /dev/null +++ b/test/hotspot/gtest/oops/test_jmethodIDTable.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "classfile/vmClasses.hpp" +#include "memory/resourceArea.hpp" +#include "oops/instanceKlass.hpp" +#include "oops/jmethodIDTable.hpp" +#include "oops/method.hpp" +#include "unittest.hpp" +#include "utilities/growableArray.hpp" + +// Tests for creating and deleting jmethodIDs +TEST_VM(jmethodIDTable, test_jmethod_ids) { + InstanceKlass* klass = vmClasses::ClassLoader_klass(); + Array* methods = klass->methods(); + int length = methods->length(); + // How many entries are in the jmethodID table? + uint64_t initial_entries = JmethodIDTable::get_entry_count(); + ResourceMark rm; + GrowableArray ints(10); + for (int i = 0; i < length; i++) { + Method* m = methods->at(i); + jmethodID mid = m->jmethod_id(); + ints.push((uint64_t)mid); + } + uint64_t entries_now = JmethodIDTable::get_entry_count(); + ASSERT_TRUE(entries_now == initial_entries + length) << "should have more entries " << entries_now << " " << initial_entries + length; + + // Test that new entries aren't created, and the values are the same. + for (int i = 0; i < length; i++) { + Method* m = methods->at(i); + jmethodID mid = m->jmethod_id(); + ASSERT_TRUE(ints.at(i) == (uint64_t)mid) << "should be the same"; + } + // should have the same number of entries + entries_now = JmethodIDTable::get_entry_count(); + ASSERT_TRUE(entries_now == initial_entries + length) << "should have more entries " << entries_now << " " << initial_entries + length; +} + From ecd2d83096a1fea7d5086736306770bcffa4fdb6 Mon Sep 17 00:00:00 2001 From: Evgeny Astigeevich Date: Fri, 27 Jun 2025 12:49:20 +0000 Subject: [PATCH 205/213] 8359435: AArch64: add support for SB instruction to MacroAssembler::spin_wait Reviewed-by: shade, aph --- src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 4 + src/hotspot/cpu/aarch64/globals_aarch64.hpp | 2 +- .../cpu/aarch64/macroAssembler_aarch64.cpp | 3 + src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp | 3 +- .../cpu/aarch64/vm_version_aarch64.cpp | 7 +- .../cpu/aarch64/vm_version_aarch64.hpp | 1 + .../bsd_aarch64/vm_version_bsd_aarch64.cpp | 3 + .../vm_version_linux_aarch64.cpp | 5 + .../classes/jdk/vm/ci/aarch64/AArch64.java | 1 + test/hotspot/gtest/aarch64/aarch64-asmtest.py | 2 +- test/hotspot/gtest/aarch64/asmtest.out.h | 583 +++++++++--------- .../onSpinWait/TestOnSpinWaitAArch64.java | 15 +- 12 files changed, 331 insertions(+), 298 deletions(-) diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 573b451261f..2e35763aa43 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -1136,6 +1136,10 @@ class Assembler : public AbstractAssembler { system(0b00, 0b011, 0b00011, SY, 0b110); } + void sb() { + system(0b00, 0b011, 0b00011, 0b0000, 0b111); + } + void sys(int op1, int CRn, int CRm, int op2, Register rt = as_Register(0b11111)) { system(0b01, op1, CRn, CRm, op2, rt); diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index d195af8cef4..ef741c2007a 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -117,7 +117,7 @@ define_pd_global(intx, InlineSmallCode, 1000); product(ccstr, OnSpinWaitInst, "yield", DIAGNOSTIC, \ "The instruction to use to implement " \ "java.lang.Thread.onSpinWait()." \ - "Options: none, nop, isb, yield.") \ + "Options: none, nop, isb, yield, sb.") \ product(uint, OnSpinWaitInstCount, 1, DIAGNOSTIC, \ "The number of OnSpinWaitInst instructions to generate." \ "It cannot be used with OnSpinWaitInst=none.") \ diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index cbd941397f3..44dbf3692f6 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -6814,6 +6814,9 @@ void MacroAssembler::spin_wait() { case SpinWait::YIELD: yield(); break; + case SpinWait::SB: + sb(); + break; default: ShouldNotReachHere(); } diff --git a/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp b/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp index 28ffeafda48..08850f05f53 100644 --- a/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/spin_wait_aarch64.hpp @@ -31,7 +31,8 @@ class SpinWait { NONE = -1, NOP, ISB, - YIELD + YIELD, + SB }; private: diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 941cb254532..6ee4a0023c6 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -57,8 +57,13 @@ static SpinWait get_spin_wait_desc() { return SpinWait(SpinWait::ISB, OnSpinWaitInstCount); } else if (strcmp(OnSpinWaitInst, "yield") == 0) { return SpinWait(SpinWait::YIELD, OnSpinWaitInstCount); + } else if (strcmp(OnSpinWaitInst, "sb") == 0) { + if (!VM_Version::supports_sb()) { + vm_exit_during_initialization("OnSpinWaitInst is SB but current CPU does not support SB instruction"); + } + return SpinWait(SpinWait::SB, OnSpinWaitInstCount); } else if (strcmp(OnSpinWaitInst, "none") != 0) { - vm_exit_during_initialization("The options for OnSpinWaitInst are nop, isb, yield, and none", OnSpinWaitInst); + vm_exit_during_initialization("The options for OnSpinWaitInst are nop, isb, yield, sb, and none", OnSpinWaitInst); } if (!FLAG_IS_DEFAULT(OnSpinWaitInstCount) && OnSpinWaitInstCount > 0) { diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 373f8da5405..99450d3dde1 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -131,6 +131,7 @@ enum Ampere_CPU_Model { decl(SHA3, sha3, 17) \ decl(SHA512, sha512, 21) \ decl(SVE, sve, 22) \ + decl(SB, sb, 29) \ decl(PACA, paca, 30) \ /* flags above must follow Linux HWCAP */ \ decl(SVEBITPERM, svebitperm, 27) \ diff --git a/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp index 5424b58da6d..b55c1cd27c8 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/vm_version_bsd_aarch64.cpp @@ -92,6 +92,9 @@ void VM_Version::get_os_cpu_info() { cpu_has("hw.optional.armv8_2_sha3")) { _features |= CPU_SHA3; } + if (cpu_has("hw.optional.arm.FEAT_SB")) { + _features |= CPU_SB; + } int cache_line_size; int hw_conf_cache_line[] = { CTL_HW, HW_CACHELINE }; diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index 9725c6cd6c0..a8edeefc885 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -71,6 +71,10 @@ #define HWCAP_SVE (1 << 22) #endif +#ifndef HWCAP_SB +#define HWCAP_SB (1 << 29) +#endif + #ifndef HWCAP_PACA #define HWCAP_PACA (1 << 30) #endif @@ -143,6 +147,7 @@ void VM_Version::get_os_cpu_info() { HWCAP_SHA3 | HWCAP_SHA512 | HWCAP_SVE | + HWCAP_SB | HWCAP_PACA | HWCAP_FPHP | HWCAP_ASIMDHP); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java index 66aed480bbb..391ac224609 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/aarch64/AArch64.java @@ -179,6 +179,7 @@ public enum CPUFeature implements CPUFeatureName { SHA3, SHA512, SVE, + SB, PACA, SVEBITPERM, SVE2, diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index b0c8cdbc330..5b2c18b0a2b 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -1605,7 +1605,7 @@ def generate(kind, names): generate (Op, ["nop", "yield", "wfe", "sev", "sevl", "autia1716", "autiasp", "autiaz", "autib1716", "autibsp", "autibz", "pacia1716", "paciasp", "paciaz", "pacib1716", "pacibsp", "pacibz", - "eret", "drps", "isb",]) + "eret", "drps", "isb", "sb",]) # Ensure the "i" is not stripped off the end of the instruction generate (PostfixExceptionOp, ["wfi", "xpaclri"]) diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index 2b4ea356d70..d90c2479995 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -187,6 +187,7 @@ __ eret(); // eret __ drps(); // drps __ isb(); // isb + __ sb(); // sb // PostfixExceptionOp __ wfi(); // wfi @@ -1437,306 +1438,306 @@ 0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061, 0x120cb166, 0x321764bc, 0x52174681, 0x720c0227, 0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01, - 0x14000000, 0x17ffffd7, 0x140004af, 0x94000000, - 0x97ffffd4, 0x940004ac, 0x3400000a, 0x34fffa2a, - 0x3400952a, 0x35000008, 0x35fff9c8, 0x350094c8, - 0xb400000b, 0xb4fff96b, 0xb400946b, 0xb500001d, - 0xb5fff91d, 0xb500941d, 0x10000013, 0x10fff8b3, - 0x100093b3, 0x90000013, 0x36300016, 0x3637f836, - 0x36309336, 0x3758000c, 0x375ff7cc, 0x375892cc, + 0x14000000, 0x17ffffd7, 0x140004b0, 0x94000000, + 0x97ffffd4, 0x940004ad, 0x3400000a, 0x34fffa2a, + 0x3400954a, 0x35000008, 0x35fff9c8, 0x350094e8, + 0xb400000b, 0xb4fff96b, 0xb400948b, 0xb500001d, + 0xb5fff91d, 0xb500943d, 0x10000013, 0x10fff8b3, + 0x100093d3, 0x90000013, 0x36300016, 0x3637f836, + 0x36309356, 0x3758000c, 0x375ff7cc, 0x375892ec, 0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc, 0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f, 0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016, 0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0, - 0x540090a0, 0x54000001, 0x54fff541, 0x54009041, - 0x54000002, 0x54fff4e2, 0x54008fe2, 0x54000002, - 0x54fff482, 0x54008f82, 0x54000003, 0x54fff423, - 0x54008f23, 0x54000003, 0x54fff3c3, 0x54008ec3, - 0x54000004, 0x54fff364, 0x54008e64, 0x54000005, - 0x54fff305, 0x54008e05, 0x54000006, 0x54fff2a6, - 0x54008da6, 0x54000007, 0x54fff247, 0x54008d47, - 0x54000008, 0x54fff1e8, 0x54008ce8, 0x54000009, - 0x54fff189, 0x54008c89, 0x5400000a, 0x54fff12a, - 0x54008c2a, 0x5400000b, 0x54fff0cb, 0x54008bcb, - 0x5400000c, 0x54fff06c, 0x54008b6c, 0x5400000d, - 0x54fff00d, 0x54008b0d, 0x5400000e, 0x54ffefae, - 0x54008aae, 0x5400000f, 0x54ffef4f, 0x54008a4f, + 0x540090c0, 0x54000001, 0x54fff541, 0x54009061, + 0x54000002, 0x54fff4e2, 0x54009002, 0x54000002, + 0x54fff482, 0x54008fa2, 0x54000003, 0x54fff423, + 0x54008f43, 0x54000003, 0x54fff3c3, 0x54008ee3, + 0x54000004, 0x54fff364, 0x54008e84, 0x54000005, + 0x54fff305, 0x54008e25, 0x54000006, 0x54fff2a6, + 0x54008dc6, 0x54000007, 0x54fff247, 0x54008d67, + 0x54000008, 0x54fff1e8, 0x54008d08, 0x54000009, + 0x54fff189, 0x54008ca9, 0x5400000a, 0x54fff12a, + 0x54008c4a, 0x5400000b, 0x54fff0cb, 0x54008beb, + 0x5400000c, 0x54fff06c, 0x54008b8c, 0x5400000d, + 0x54fff00d, 0x54008b2d, 0x5400000e, 0x54ffefae, + 0x54008ace, 0x5400000f, 0x54ffef4f, 0x54008a6f, 0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60, 0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f, 0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf, 0xd503239f, 0xd50321df, 0xd50323ff, 0xd50323df, 0xd503211f, 0xd503233f, 0xd503231f, 0xd503215f, 0xd503237f, 0xd503235f, 0xd69f03e0, 0xd6bf03e0, - 0xd5033fdf, 0xd503207f, 0xd50320ff, 0xd5033e9f, - 0xd50332bf, 0xd61f0200, 0xd63f0280, 0xdac123ea, - 0xdac127fb, 0xdac12be8, 0xdac12fe0, 0xdac133e1, - 0xdac137f5, 0xdac13bf1, 0xdac13ffd, 0xdac147fd, - 0xd61f0b9f, 0xd61f0c3f, 0xd63f0aff, 0xd63f0ebf, - 0xd51b4434, 0xd51b4216, 0xd53b443b, 0xd53b4213, - 0xd53b00eb, 0xd53b0030, 0xdac143e6, 0xc8117c80, - 0xc80afed8, 0xc85f7e6a, 0xc85ffca1, 0xc89ffd1e, - 0xc8dffe2c, 0x88097cee, 0x8801fe05, 0x885f7d82, - 0x885ffd8a, 0x889fff83, 0x88dfff4e, 0x481e7dca, - 0x4815fd2d, 0x485f7f76, 0x485ffe7c, 0x489fffcb, - 0x48dffc53, 0x08027c37, 0x0800fe0c, 0x085f7ded, - 0x085ffeb1, 0x089ffd6d, 0x08dffd1e, 0xc87f3578, - 0xc87feaa1, 0xc83b506d, 0xc82c87a6, 0x887f1166, - 0x887f93d0, 0x883e32a4, 0x883bf12f, 0xf80011f9, - 0xb81b1022, 0x381ea354, 0x79002fd7, 0xf85cf39a, - 0xb8580309, 0x385e218c, 0x784051e1, 0x389e11d8, - 0x789fa1f8, 0x79c01865, 0xb881131b, 0xfc5dd3ad, - 0xbc5d1137, 0xfc00900b, 0xbc181015, 0xf818ec7d, - 0xb81b8c91, 0x381efc40, 0x78007c3d, 0xf857beb0, - 0xb8413dd4, 0x385fddd6, 0x78409e2f, 0x389eddea, - 0x789e7d94, 0x78de3d55, 0xb8805c13, 0xfc5cadc0, - 0xbc428c23, 0xfc1a2dc4, 0xbc1caf92, 0xf81475f6, - 0xb81f95d1, 0x381e757e, 0x78014561, 0xf8402436, - 0xb85896e2, 0x385f4763, 0x785db4f0, 0x3880374f, - 0x789e25e7, 0x78dd0563, 0xb88166f9, 0xfc529540, - 0xbc4374d3, 0xfc1166ae, 0xbc1ba6c0, 0xf820ea7b, - 0xb82d68c8, 0x38367a04, 0x782f4b59, 0xf878c8a4, - 0xb8674a24, 0x386b78f1, 0x78776bc0, 0x38a15aca, - 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, 0xfc6ecbbe, - 0xbc65d8a8, 0xfc2de919, 0xbc3a7b11, 0xf91f1193, - 0xb91ed5f7, 0x391ec9bd, 0x79182ceb, 0xf95d4b0a, - 0xb9581010, 0x395fc034, 0x795fb221, 0x399d8731, - 0x799efb3b, 0x79dd1a2e, 0xb998e4ea, 0xfd583723, - 0xbd5ea12c, 0xfd18dc38, 0xbd1b0e83, 0x58ffdaa2, - 0x1800001d, 0xf885d1c0, 0xd8ffda40, 0xf8a77820, - 0xf9980220, 0x1a030301, 0x3a140311, 0x5a0d000b, - 0x7a07015c, 0x9a1001e4, 0xba140182, 0xda0d01bd, - 0xfa0c00ce, 0x0b31f194, 0x2b206d7b, 0xcb29f027, - 0x6b210f63, 0x8b2cb34d, 0xab2a88b1, 0xcb2f511e, - 0xeb3332f3, 0x3a4533aa, 0x7a4d312b, 0xba442146, - 0xfa42818c, 0x3a466a02, 0x7a4b68ed, 0xba4a9b6b, - 0xfa4dd86d, 0x1a8a637a, 0x1a9cd6aa, 0x5a9bd137, - 0x5a8fd7aa, 0x9a95233e, 0x9a95c620, 0xda9422b0, - 0xda8397d3, 0x5ac00173, 0x5ac00418, 0x5ac00b3b, - 0x5ac0106e, 0x5ac0162e, 0xdac001e7, 0xdac00798, - 0xdac00b31, 0xdac00f42, 0xdac010bc, 0xdac01759, - 0xdac1021b, 0xdac104d1, 0xdac10995, 0xdac10c80, - 0xdac1136c, 0xdac11791, 0xdac1185c, 0xdac11d51, - 0xd71f09ee, 0xd71f0dc3, 0xd73f0b2f, 0xd73f0e6e, - 0x1ac40a05, 0x1ac40f3a, 0x1acc2042, 0x1ac8263d, - 0x1ac42867, 0x1ada2c99, 0x9ad10899, 0x9ad10f40, - 0x9ad521f7, 0x9adb263c, 0x9ac0286a, 0x9ac92f27, - 0x9bdd7de6, 0x9b427d4f, 0x1b0b2cf1, 0x1b1ddcf7, - 0x9b0b2f6e, 0x9b0cbf04, 0x9b2b728e, 0x9b2cdd6d, - 0x9bae275e, 0x9ba7954d, 0x7ec315fe, 0x1ef0098c, - 0x1ef21bff, 0x1ef02ab3, 0x1ef5394f, 0x1efc4942, - 0x1eff5bc7, 0x1ee28832, 0x7ea3d546, 0x1e270979, - 0x1e201981, 0x1e3d2a63, 0x1e263ae6, 0x1e3b4b80, - 0x1e2758a2, 0x1e39899d, 0x7ef8d58d, 0x1e720913, - 0x1e751b56, 0x1e622a74, 0x1e683ade, 0x1e754a76, - 0x1e755a4c, 0x1e638a06, 0x1fc373a3, 0x1f0a35cf, - 0x1f0aea4c, 0x1f2f74e7, 0x1f2032e0, 0x1f4d21d8, - 0x1f49d0ef, 0x1f7f43b3, 0x1f705522, 0x1e20409e, - 0x1e20c361, 0x1e214319, 0x1e21c2ae, 0x1e22c0cd, - 0x1e23c32c, 0x1ee243d9, 0x1e6042bc, 0x1e60c2f0, - 0x1e6143a5, 0x1e61c276, 0x1e62428d, 0x1ee1c393, - 0x1e3800d1, 0x9e3800ed, 0x1e78035c, 0x9e7800d1, - 0x1e220081, 0x9e22028e, 0x1e6202a7, 0x9e6202fb, - 0x1e24028d, 0x9e64039e, 0x1e3002aa, 0x9e700225, - 0x1e2601cb, 0x9e6602ad, 0x1e2701db, 0x9e6702e4, - 0x1e3e2300, 0x1e6e2180, 0x1e202228, 0x1e602388, - 0x29021b40, 0x297c78c0, 0x69660970, 0xa908018f, - 0xa9427ae7, 0x29a03cfa, 0x29fc3d4b, 0x69c84033, - 0xa988240e, 0xa9fa0d9b, 0x28a02d88, 0x28c8408a, - 0x68f87a6a, 0xa8ba09f8, 0xa8c52a18, 0x280257be, - 0x28727948, 0xa83868de, 0xa8440a98, 0x0c40733f, - 0x4cdfa1e5, 0x0ccd6cea, 0x4cdf260d, 0x0d40c227, - 0x4ddfcb30, 0x0dc7cc6b, 0x4c408ced, 0x0cdf8769, - 0x4d60c346, 0x0dffca17, 0x4de8cda6, 0x4cda4834, - 0x0c4049ef, 0x4d40e6dd, 0x4ddfe946, 0x0dcfeccf, - 0x4cdf0546, 0x0cc7006b, 0x0d60e32c, 0x0dffe5eb, - 0x0dfce8de, 0x0e31bb9b, 0x4e31bbbc, 0x0e71b841, - 0x4e71bbbc, 0x4eb1b841, 0x0e30aab4, 0x4e30abdd, - 0x0e70aa30, 0x4e70a9cd, 0x4eb0a96a, 0x6e30fbdd, - 0x0e31abdd, 0x2e31aa93, 0x4e31aaf6, 0x6e31a96a, - 0x0e71a8a4, 0x2e71a81f, 0x4e71aad5, 0x6e71a928, - 0x4eb1a81f, 0x6eb1aa93, 0x6eb0f96a, 0x7e30fbbc, - 0x7e70f862, 0x7eb0fb59, 0x7ef0f8c5, 0x0ea0c883, - 0x4ea0c928, 0x4ee0caf6, 0x2ea0ca93, 0x6ea0c9cd, - 0x6ee0c8c5, 0x0ea0dbdd, 0x4ea0db38, 0x4ee0dad5, - 0x0ea0eb7a, 0x4ea0eb38, 0x4ee0e883, 0x2ea0db38, - 0x6ea0db7a, 0x6ee0db17, 0x0e20ba0f, 0x4e20bad5, - 0x0e60b883, 0x4e60bb38, 0x0ea0b928, 0x4ea0bb59, - 0x4ee0bab4, 0x0ea0fa30, 0x4ea0fa51, 0x4ee0f862, - 0x0ef8f841, 0x4ef8f820, 0x2ea0fb38, 0x6ea0f8a4, - 0x6ee0f883, 0x2ef8f9ac, 0x6ef8f81f, 0x2ea1fbbc, - 0x6ea1f96a, 0x6ee1fb7a, 0x2ef9f862, 0x6ef9f9ac, - 0x2e205a72, 0x6e20581f, 0x0e231c41, 0x4e2f1dcd, - 0x0ebf1fdd, 0x4ea21c20, 0x2e351e93, 0x6e2e1dac, - 0x0e338651, 0x4e3886f6, 0x0e6f85cd, 0x4e7e87bc, - 0x0ea087fe, 0x4ea1841f, 0x4ee38441, 0x0e3c0f7a, - 0x4e3e0fbc, 0x0e660ca4, 0x4e600ffe, 0x0ea60ca4, - 0x4ea80ce6, 0x4ee00ffe, 0x2e3c0f7a, 0x6e340e72, - 0x2e6b0d49, 0x6e6a0d28, 0x2eae0dac, 0x6ea20c20, - 0x6ef60eb4, 0x0e23d441, 0x4e3ad738, 0x4e64d462, - 0x0e421420, 0x4e4b1549, 0x2e3a8738, 0x6e3c877a, - 0x2e728630, 0x6e6087fe, 0x2ea58483, 0x6eac856a, - 0x6ef98717, 0x0e2c2d6a, 0x4e262ca4, 0x0e742e72, - 0x4e642c62, 0x0ead2d8b, 0x4eaa2d28, 0x4eec2d6a, - 0x2e312e0f, 0x6e332e51, 0x2e642c62, 0x6e6c2d6a, - 0x2eae2dac, 0x6eae2dac, 0x6ef12e0f, 0x0eafd5cd, - 0x4ea4d462, 0x4ee9d507, 0x0ed616b4, 0x4edc177a, - 0x0e329e30, 0x4e269ca4, 0x0e649c62, 0x4e669ca4, - 0x0eae9dac, 0x4eb49e72, 0x2eb7d6d5, 0x6eb2d630, - 0x6ef4d672, 0x2ecd158b, 0x6ed716d5, 0x2e39d717, - 0x6e2ed5ac, 0x6e7cd77a, 0x2e591717, 0x6e5e17bc, - 0x2e30ddee, 0x6e2ddd8b, 0x6e7adf38, 0x2e431c41, - 0x6e4e1dac, 0x0e61941f, 0x4e6c956a, 0x0eb29630, - 0x4ea99507, 0x0e24cc62, 0x4e25cc83, 0x4e6fcdcd, - 0x0e550e93, 0x4e530e51, 0x2e729630, 0x6e659483, - 0x2ea39441, 0x6ead958b, 0x0ea0cffe, 0x4ea7ccc5, - 0x4eeacd28, 0x0ed10e0f, 0x4edf0fdd, 0x2e20fffe, - 0x6e22fc20, 0x6e76feb4, 0x2e493d07, 0x6e563eb4, - 0x0e396717, 0x4e3e67bc, 0x0e7766d5, 0x4e7d679b, - 0x0ebb6759, 0x4ea764c5, 0x2e236441, 0x6e396717, - 0x2e726630, 0x6e61641f, 0x2ea764c5, 0x6eae65ac, - 0x0e2ba549, 0x4e3ea7bc, 0x0e71a60f, 0x4e7fa7dd, - 0x0eb8a6f6, 0x4ea1a41f, 0x0e35f693, 0x4e21f41f, - 0x4e67f4c5, 0x0e5035ee, 0x4e543672, 0x0e216c1f, - 0x4e346e72, 0x0e7d6f9b, 0x4e766eb4, 0x0eb26e30, - 0x4eae6dac, 0x2e2d6d8b, 0x6e2b6d49, 0x2e686ce6, - 0x6e606ffe, 0x2eb36e51, 0x6ebd6f9b, 0x0e3eafbc, - 0x4e20affe, 0x0e69ad07, 0x4e6cad6a, 0x0eb6aeb4, - 0x4eacad6a, 0x0e66b4a4, 0x4e7ab738, 0x0eb3b651, - 0x4eb3b651, 0x0e3826f6, 0x4e252483, 0x0e7f27dd, - 0x4e71260f, 0x0eb826f6, 0x4eb52693, 0x0eb5f693, - 0x4eb8f6f6, 0x4ee4f462, 0x0ed1360f, 0x4ec834e6, - 0x2eaeedac, 0x6eb2ee30, 0x6eeded8b, 0x2ecf2dcd, - 0x6ed92f17, 0x0f81100f, 0x4f848862, 0x4fc31841, - 0x0fad518b, 0x4fa780c5, 0x4fd059ee, 0x2fa890e6, - 0x4fa38841, 0x6fc1900f, 0x0f7b8149, 0x4f4688a4, - 0x0faf81cd, 0x4fa58083, 0x0e3736d5, 0x4e393717, - 0x0e61341f, 0x4e7b3759, 0x0ea43462, 0x4ea1341f, - 0x4efd379b, 0x0e343e72, 0x4e2c3d6a, 0x0e793f17, - 0x4e753e93, 0x0ea53c83, 0x4eb43e72, 0x4ee23c20, - 0x2e3b8f59, 0x6e3c8f7a, 0x2e798f17, 0x6e648c62, - 0x2eb48e72, 0x6eae8dac, 0x6ee68ca4, 0x2e3e37bc, - 0x6e2037fe, 0x2e7f37dd, 0x6e723630, 0x2ebd379b, - 0x6ea834e6, 0x6eeb3549, 0x2e3f3fdd, 0x6e343e72, - 0x2e693d07, 0x6e663ca4, 0x2ea93d07, 0x6eb13e0f, - 0x6eeb3d49, 0x0e39e717, 0x4e2ae528, 0x4e64e462, - 0x2ebee7bc, 0x6eb7e6d5, 0x6ee1e41f, 0x2e27e4c5, - 0x6e3de79b, 0x6e62e420, 0x659239e8, 0x65d03b94, - 0x65d0232d, 0x65d120c2, 0x659129f2, 0x65933ca3, - 0x25969683, 0x25961d15, 0x254d1c48, 0x259e3f61, - 0x25953b96, 0x255b91d1, 0x247686ed, 0x24309098, - 0x2462edb9, 0x24a57468, 0xba5fd3e3, 0x3a5f03e5, - 0xfa411be4, 0x7a42cbe2, 0x93df03ff, 0xc820ffff, - 0x8822fc7f, 0xc8247cbf, 0x88267fff, 0x4e010fe0, - 0x5e040420, 0x4e081fe1, 0x4e0c1fe1, 0x4e0a1fe1, - 0x4e071fe1, 0x4e042c20, 0x4e062c20, 0x4e052c20, - 0x4e083c20, 0x0e0c3c20, 0x0e0a3c20, 0x0e073c20, - 0x9eae0020, 0x0f03f409, 0x6f03f40e, 0x4cc0ac3f, - 0x0ea1b820, 0x0ef9b820, 0x4ef9b820, 0x4e21c862, - 0x0e79c862, 0x4e79c862, 0x4e61b8a4, 0x0e79b8a4, - 0x4e79b8a4, 0x05a08020, 0x05104fe0, 0x05505001, - 0x05906fe2, 0x05d03005, 0x05101fea, 0x05901feb, - 0x04b0e3e0, 0x0470e7e1, 0x042f9c20, 0x043f9c35, - 0x047f9c20, 0x04ff9c20, 0x04299420, 0x04319160, - 0x0461943e, 0x04a19020, 0x04038100, 0x040381a0, - 0x040387e1, 0x04438be2, 0x04c38fe3, 0x040181e0, - 0x04018100, 0x04018621, 0x04418b22, 0x04418822, - 0x04818c23, 0x040081e0, 0x04008120, 0x04008761, - 0x04008621, 0x04408822, 0x04808c23, 0x042053ff, - 0x047f5401, 0x25208028, 0x2538cfe0, 0x2578d001, - 0x25b8efe2, 0x25f8f007, 0x2538dfea, 0x25b8dfeb, - 0xa400a3e0, 0xa420a7e0, 0xa4484be0, 0xa467afe0, - 0xa4a8a7ea, 0xa547a814, 0xa4084ffe, 0xa55c53e0, - 0xa5e1540b, 0xe400fbf6, 0xe408ffff, 0xe420e7e0, - 0xe4484be0, 0xe460efe0, 0xe547e400, 0xe4014be0, - 0xe4a84fe0, 0xe5f15000, 0x858043e0, 0x85a043ff, - 0xe59f5d08, 0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, - 0x04e0e3ec, 0x25104042, 0x25104871, 0x25904861, - 0x25904c92, 0x05344020, 0x05744041, 0x05b44062, - 0x05f44083, 0x252c8840, 0x253c1420, 0x25681572, - 0x25a21ce3, 0x25ea1e34, 0x253c0421, 0x25680572, - 0x25a20ce3, 0x25ea0e34, 0x0522c020, 0x05e6c0a4, - 0x2401a001, 0x2443a051, 0x24858881, 0x24c78cd1, - 0x24850891, 0x24c70cc1, 0x250f9001, 0x25508051, - 0x25802491, 0x25df28c1, 0x25850c81, 0x251e10d1, - 0x65816001, 0x65c36051, 0x65854891, 0x65c74cc1, - 0x05733820, 0x05b238a4, 0x05f138e6, 0x0570396a, - 0x65d0a001, 0x65d6a443, 0x65d4a826, 0x6594ac26, - 0x6554ac26, 0x6556ac26, 0x6552ac26, 0x65cbac85, - 0x65caac01, 0x6589ac85, 0x6588ac01, 0x65c9ac85, - 0x65c8ac01, 0x65dea833, 0x659ca509, 0x65d8a801, - 0x65dcac01, 0x655cb241, 0x0520a1e0, 0x0521a601, - 0x052281e0, 0x05238601, 0x04a14026, 0x042244a6, - 0x046344a6, 0x04a444a6, 0x04e544a7, 0x0568aca7, - 0x05b23230, 0x853040af, 0xc5b040af, 0xe57080af, - 0xe5b080af, 0x25034440, 0x254054c4, 0x25034640, - 0x25415a05, 0x25834440, 0x25c54489, 0x250b5d3a, - 0x2550dc20, 0x2518e3e1, 0x2518e021, 0x2518e0a1, - 0x2518e121, 0x2518e1a1, 0x2558e3e2, 0x2558e042, - 0x2558e0c2, 0x2558e142, 0x2598e3e3, 0x2598e063, - 0x2598e0e3, 0x2598e163, 0x25d8e3e4, 0x25d8e084, - 0x25d8e104, 0x25d8e184, 0x2518e407, 0x05214800, - 0x05614800, 0x05a14800, 0x05e14800, 0x05214c00, - 0x05614c00, 0x05a14c00, 0x05e14c00, 0x05304001, - 0x05314001, 0x05a18610, 0x05e18610, 0x05271e11, - 0x6545e891, 0x6585e891, 0x65c5e891, 0x6545c891, - 0x6585c891, 0x65c5c891, 0x45b0c210, 0x45f1c231, - 0x1e601000, 0x1e603000, 0x1e621000, 0x1e623000, - 0x1e641000, 0x1e643000, 0x1e661000, 0x1e663000, - 0x1e681000, 0x1e683000, 0x1e6a1000, 0x1e6a3000, - 0x1e6c1000, 0x1e6c3000, 0x1e6e1000, 0x1e6e3000, - 0x1e701000, 0x1e703000, 0x1e721000, 0x1e723000, - 0x1e741000, 0x1e743000, 0x1e761000, 0x1e763000, - 0x1e781000, 0x1e783000, 0x1e7a1000, 0x1e7a3000, - 0x1e7c1000, 0x1e7c3000, 0x1e7e1000, 0x1e7e3000, - 0xf8268267, 0xf82d023c, 0xf8301046, 0xf83d2083, - 0xf8263290, 0xf82d528c, 0xf8284299, 0xf8337160, - 0xf8386286, 0xf8bf820e, 0xf8a600e0, 0xf8af1353, - 0xf8a922ea, 0xf8b53396, 0xf8a251e3, 0xf8b340f4, - 0xf8a470fd, 0xf8a06209, 0xf8f48097, 0xf8f002ea, - 0xf8eb10d9, 0xf8ff21b0, 0xf8f7302c, 0xf8ee52a9, - 0xf8f041fa, 0xf8e471e4, 0xf8e863c6, 0xf864823d, - 0xf87d013a, 0xf86f1162, 0xf87d20e3, 0xf86132bb, - 0xf870510e, 0xf8704336, 0xf86572b4, 0xf8706217, - 0xb83e8294, 0xb8200264, 0xb8381284, 0xb8242358, - 0xb8333102, 0xb828530e, 0xb83042df, 0xb824703f, - 0xb82a6194, 0xb8a080e9, 0xb8b80090, 0xb8bb1146, - 0xb8bb21b8, 0xb8b032df, 0xb8b653f4, 0xb8bd41c9, - 0xb8b47287, 0xb8bc6169, 0xb8ee828c, 0xb8e10138, - 0xb8f3126d, 0xb8f020b0, 0xb8e03183, 0xb8e851ef, - 0xb8f041e4, 0xb8fe7005, 0xb8ea6376, 0xb8638120, - 0xb873015d, 0xb8781284, 0xb86723b8, 0xb86e3175, - 0xb87b51ed, 0xb87f41d1, 0xb863721e, 0xb87660f4, - 0xce216874, 0xce104533, 0xce648c15, 0xce8e3302, - 0xce6e82ab, 0xce6c87d1, 0xcec08063, 0xce638937, - 0x25e0c358, 0x25a1c7d3, 0x0580785a, 0x05426328, - 0x05009892, 0x25a0cc29, 0x2561cec8, 0x058044b3, - 0x05401c99, 0x05006b49, 0x25e0d6f7, 0x2561c528, - 0x0583c8bc, 0x0542522f, 0x05001ec0, 0x25e0de65, - 0x25a1c113, 0x05803cad, 0x0540f3c0, 0x0500ab15, - 0x2560c28c, 0x2561d7c0, 0x05801ed7, 0x0542633b, - 0x05003696, 0x2560d4b4, 0x25e1c918, 0x058021ff, - 0x05400e15, 0x0500f3de, 0x0473025a, 0x04bd05ab, - 0x658e0025, 0x658a08e2, 0x659a0493, 0x043e1062, - 0x04f418b4, 0x046d15bd, 0x04611fce, 0x04d6a07c, - 0x04001929, 0x041a09da, 0x04d098f4, 0x04db10d4, - 0x0459a3ad, 0x041aa029, 0x041919fb, 0x04d39e24, - 0x04118302, 0x04101dba, 0x04d7ae16, 0x04dea571, - 0x04180210, 0x05e786fc, 0x05e4915c, 0x04881cf1, - 0x044a0f04, 0x04090969, 0x048b16c4, 0x044101e4, - 0x04dcbf44, 0x65809745, 0x658d833f, 0x65c68468, - 0x65c79b07, 0x65829e38, 0x049dafca, 0x6582bba8, - 0x65c0b7ff, 0x65c1b4e0, 0x658dbadd, 0x65819a9d, - 0x65ed9246, 0x65b30815, 0x65e6263c, 0x65eebb94, - 0x65bad14e, 0x65efe178, 0x65fc5697, 0x65e07f14, - 0x040c55a6, 0x04977f4d, 0x043d3046, 0x04b733a0, - 0x046830a4, 0x04ed322d, 0x05686948, 0x05bd6c13, - 0x65c88ef0, 0x450db3d7, 0x4540b6d9, 0x043e3979, - 0x445896ce, 0x445a9005, 0x44d98069, 0x445b87ae, - 0x04da348e, 0x04982edb, 0x0499397f, 0x0408338c, - 0x04ca309c, 0x65c721e6, 0x65c63641, 0x65982882, - 0x04812b8b, 0x0e251083, 0x4e3712d5, 0x0e61101f, - 0x4e6d118b, 0x0eba1338, 0x4eb712d5, 0x2e31120f, - 0x6e2e11ac, 0x2e6810e6, 0x6e6f11cd, 0x2eaa1128, - 0x6eb1120f, + 0xd5033fdf, 0xd50330ff, 0xd503207f, 0xd50320ff, + 0xd5033e9f, 0xd50332bf, 0xd61f0200, 0xd63f0280, + 0xdac123ea, 0xdac127fb, 0xdac12be8, 0xdac12fe0, + 0xdac133e1, 0xdac137f5, 0xdac13bf1, 0xdac13ffd, + 0xdac147fd, 0xd61f0b9f, 0xd61f0c3f, 0xd63f0aff, + 0xd63f0ebf, 0xd51b4434, 0xd51b4216, 0xd53b443b, + 0xd53b4213, 0xd53b00eb, 0xd53b0030, 0xdac143e6, + 0xc8117c80, 0xc80afed8, 0xc85f7e6a, 0xc85ffca1, + 0xc89ffd1e, 0xc8dffe2c, 0x88097cee, 0x8801fe05, + 0x885f7d82, 0x885ffd8a, 0x889fff83, 0x88dfff4e, + 0x481e7dca, 0x4815fd2d, 0x485f7f76, 0x485ffe7c, + 0x489fffcb, 0x48dffc53, 0x08027c37, 0x0800fe0c, + 0x085f7ded, 0x085ffeb1, 0x089ffd6d, 0x08dffd1e, + 0xc87f3578, 0xc87feaa1, 0xc83b506d, 0xc82c87a6, + 0x887f1166, 0x887f93d0, 0x883e32a4, 0x883bf12f, + 0xf80011f9, 0xb81b1022, 0x381ea354, 0x79002fd7, + 0xf85cf39a, 0xb8580309, 0x385e218c, 0x784051e1, + 0x389e11d8, 0x789fa1f8, 0x79c01865, 0xb881131b, + 0xfc5dd3ad, 0xbc5d1137, 0xfc00900b, 0xbc181015, + 0xf818ec7d, 0xb81b8c91, 0x381efc40, 0x78007c3d, + 0xf857beb0, 0xb8413dd4, 0x385fddd6, 0x78409e2f, + 0x389eddea, 0x789e7d94, 0x78de3d55, 0xb8805c13, + 0xfc5cadc0, 0xbc428c23, 0xfc1a2dc4, 0xbc1caf92, + 0xf81475f6, 0xb81f95d1, 0x381e757e, 0x78014561, + 0xf8402436, 0xb85896e2, 0x385f4763, 0x785db4f0, + 0x3880374f, 0x789e25e7, 0x78dd0563, 0xb88166f9, + 0xfc529540, 0xbc4374d3, 0xfc1166ae, 0xbc1ba6c0, + 0xf820ea7b, 0xb82d68c8, 0x38367a04, 0x782f4b59, + 0xf878c8a4, 0xb8674a24, 0x386b78f1, 0x78776bc0, + 0x38a15aca, 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, + 0xfc6ecbbe, 0xbc65d8a8, 0xfc2de919, 0xbc3a7b11, + 0xf91f1193, 0xb91ed5f7, 0x391ec9bd, 0x79182ceb, + 0xf95d4b0a, 0xb9581010, 0x395fc034, 0x795fb221, + 0x399d8731, 0x799efb3b, 0x79dd1a2e, 0xb998e4ea, + 0xfd583723, 0xbd5ea12c, 0xfd18dc38, 0xbd1b0e83, + 0x58ffda82, 0x1800001d, 0xf885d1c0, 0xd8ffda20, + 0xf8a77820, 0xf9980220, 0x1a030301, 0x3a140311, + 0x5a0d000b, 0x7a07015c, 0x9a1001e4, 0xba140182, + 0xda0d01bd, 0xfa0c00ce, 0x0b31f194, 0x2b206d7b, + 0xcb29f027, 0x6b210f63, 0x8b2cb34d, 0xab2a88b1, + 0xcb2f511e, 0xeb3332f3, 0x3a4533aa, 0x7a4d312b, + 0xba442146, 0xfa42818c, 0x3a466a02, 0x7a4b68ed, + 0xba4a9b6b, 0xfa4dd86d, 0x1a8a637a, 0x1a9cd6aa, + 0x5a9bd137, 0x5a8fd7aa, 0x9a95233e, 0x9a95c620, + 0xda9422b0, 0xda8397d3, 0x5ac00173, 0x5ac00418, + 0x5ac00b3b, 0x5ac0106e, 0x5ac0162e, 0xdac001e7, + 0xdac00798, 0xdac00b31, 0xdac00f42, 0xdac010bc, + 0xdac01759, 0xdac1021b, 0xdac104d1, 0xdac10995, + 0xdac10c80, 0xdac1136c, 0xdac11791, 0xdac1185c, + 0xdac11d51, 0xd71f09ee, 0xd71f0dc3, 0xd73f0b2f, + 0xd73f0e6e, 0x1ac40a05, 0x1ac40f3a, 0x1acc2042, + 0x1ac8263d, 0x1ac42867, 0x1ada2c99, 0x9ad10899, + 0x9ad10f40, 0x9ad521f7, 0x9adb263c, 0x9ac0286a, + 0x9ac92f27, 0x9bdd7de6, 0x9b427d4f, 0x1b0b2cf1, + 0x1b1ddcf7, 0x9b0b2f6e, 0x9b0cbf04, 0x9b2b728e, + 0x9b2cdd6d, 0x9bae275e, 0x9ba7954d, 0x7ec315fe, + 0x1ef0098c, 0x1ef21bff, 0x1ef02ab3, 0x1ef5394f, + 0x1efc4942, 0x1eff5bc7, 0x1ee28832, 0x7ea3d546, + 0x1e270979, 0x1e201981, 0x1e3d2a63, 0x1e263ae6, + 0x1e3b4b80, 0x1e2758a2, 0x1e39899d, 0x7ef8d58d, + 0x1e720913, 0x1e751b56, 0x1e622a74, 0x1e683ade, + 0x1e754a76, 0x1e755a4c, 0x1e638a06, 0x1fc373a3, + 0x1f0a35cf, 0x1f0aea4c, 0x1f2f74e7, 0x1f2032e0, + 0x1f4d21d8, 0x1f49d0ef, 0x1f7f43b3, 0x1f705522, + 0x1e20409e, 0x1e20c361, 0x1e214319, 0x1e21c2ae, + 0x1e22c0cd, 0x1e23c32c, 0x1ee243d9, 0x1e6042bc, + 0x1e60c2f0, 0x1e6143a5, 0x1e61c276, 0x1e62428d, + 0x1ee1c393, 0x1e3800d1, 0x9e3800ed, 0x1e78035c, + 0x9e7800d1, 0x1e220081, 0x9e22028e, 0x1e6202a7, + 0x9e6202fb, 0x1e24028d, 0x9e64039e, 0x1e3002aa, + 0x9e700225, 0x1e2601cb, 0x9e6602ad, 0x1e2701db, + 0x9e6702e4, 0x1e3e2300, 0x1e6e2180, 0x1e202228, + 0x1e602388, 0x29021b40, 0x297c78c0, 0x69660970, + 0xa908018f, 0xa9427ae7, 0x29a03cfa, 0x29fc3d4b, + 0x69c84033, 0xa988240e, 0xa9fa0d9b, 0x28a02d88, + 0x28c8408a, 0x68f87a6a, 0xa8ba09f8, 0xa8c52a18, + 0x280257be, 0x28727948, 0xa83868de, 0xa8440a98, + 0x0c40733f, 0x4cdfa1e5, 0x0ccd6cea, 0x4cdf260d, + 0x0d40c227, 0x4ddfcb30, 0x0dc7cc6b, 0x4c408ced, + 0x0cdf8769, 0x4d60c346, 0x0dffca17, 0x4de8cda6, + 0x4cda4834, 0x0c4049ef, 0x4d40e6dd, 0x4ddfe946, + 0x0dcfeccf, 0x4cdf0546, 0x0cc7006b, 0x0d60e32c, + 0x0dffe5eb, 0x0dfce8de, 0x0e31bb9b, 0x4e31bbbc, + 0x0e71b841, 0x4e71bbbc, 0x4eb1b841, 0x0e30aab4, + 0x4e30abdd, 0x0e70aa30, 0x4e70a9cd, 0x4eb0a96a, + 0x6e30fbdd, 0x0e31abdd, 0x2e31aa93, 0x4e31aaf6, + 0x6e31a96a, 0x0e71a8a4, 0x2e71a81f, 0x4e71aad5, + 0x6e71a928, 0x4eb1a81f, 0x6eb1aa93, 0x6eb0f96a, + 0x7e30fbbc, 0x7e70f862, 0x7eb0fb59, 0x7ef0f8c5, + 0x0ea0c883, 0x4ea0c928, 0x4ee0caf6, 0x2ea0ca93, + 0x6ea0c9cd, 0x6ee0c8c5, 0x0ea0dbdd, 0x4ea0db38, + 0x4ee0dad5, 0x0ea0eb7a, 0x4ea0eb38, 0x4ee0e883, + 0x2ea0db38, 0x6ea0db7a, 0x6ee0db17, 0x0e20ba0f, + 0x4e20bad5, 0x0e60b883, 0x4e60bb38, 0x0ea0b928, + 0x4ea0bb59, 0x4ee0bab4, 0x0ea0fa30, 0x4ea0fa51, + 0x4ee0f862, 0x0ef8f841, 0x4ef8f820, 0x2ea0fb38, + 0x6ea0f8a4, 0x6ee0f883, 0x2ef8f9ac, 0x6ef8f81f, + 0x2ea1fbbc, 0x6ea1f96a, 0x6ee1fb7a, 0x2ef9f862, + 0x6ef9f9ac, 0x2e205a72, 0x6e20581f, 0x0e231c41, + 0x4e2f1dcd, 0x0ebf1fdd, 0x4ea21c20, 0x2e351e93, + 0x6e2e1dac, 0x0e338651, 0x4e3886f6, 0x0e6f85cd, + 0x4e7e87bc, 0x0ea087fe, 0x4ea1841f, 0x4ee38441, + 0x0e3c0f7a, 0x4e3e0fbc, 0x0e660ca4, 0x4e600ffe, + 0x0ea60ca4, 0x4ea80ce6, 0x4ee00ffe, 0x2e3c0f7a, + 0x6e340e72, 0x2e6b0d49, 0x6e6a0d28, 0x2eae0dac, + 0x6ea20c20, 0x6ef60eb4, 0x0e23d441, 0x4e3ad738, + 0x4e64d462, 0x0e421420, 0x4e4b1549, 0x2e3a8738, + 0x6e3c877a, 0x2e728630, 0x6e6087fe, 0x2ea58483, + 0x6eac856a, 0x6ef98717, 0x0e2c2d6a, 0x4e262ca4, + 0x0e742e72, 0x4e642c62, 0x0ead2d8b, 0x4eaa2d28, + 0x4eec2d6a, 0x2e312e0f, 0x6e332e51, 0x2e642c62, + 0x6e6c2d6a, 0x2eae2dac, 0x6eae2dac, 0x6ef12e0f, + 0x0eafd5cd, 0x4ea4d462, 0x4ee9d507, 0x0ed616b4, + 0x4edc177a, 0x0e329e30, 0x4e269ca4, 0x0e649c62, + 0x4e669ca4, 0x0eae9dac, 0x4eb49e72, 0x2eb7d6d5, + 0x6eb2d630, 0x6ef4d672, 0x2ecd158b, 0x6ed716d5, + 0x2e39d717, 0x6e2ed5ac, 0x6e7cd77a, 0x2e591717, + 0x6e5e17bc, 0x2e30ddee, 0x6e2ddd8b, 0x6e7adf38, + 0x2e431c41, 0x6e4e1dac, 0x0e61941f, 0x4e6c956a, + 0x0eb29630, 0x4ea99507, 0x0e24cc62, 0x4e25cc83, + 0x4e6fcdcd, 0x0e550e93, 0x4e530e51, 0x2e729630, + 0x6e659483, 0x2ea39441, 0x6ead958b, 0x0ea0cffe, + 0x4ea7ccc5, 0x4eeacd28, 0x0ed10e0f, 0x4edf0fdd, + 0x2e20fffe, 0x6e22fc20, 0x6e76feb4, 0x2e493d07, + 0x6e563eb4, 0x0e396717, 0x4e3e67bc, 0x0e7766d5, + 0x4e7d679b, 0x0ebb6759, 0x4ea764c5, 0x2e236441, + 0x6e396717, 0x2e726630, 0x6e61641f, 0x2ea764c5, + 0x6eae65ac, 0x0e2ba549, 0x4e3ea7bc, 0x0e71a60f, + 0x4e7fa7dd, 0x0eb8a6f6, 0x4ea1a41f, 0x0e35f693, + 0x4e21f41f, 0x4e67f4c5, 0x0e5035ee, 0x4e543672, + 0x0e216c1f, 0x4e346e72, 0x0e7d6f9b, 0x4e766eb4, + 0x0eb26e30, 0x4eae6dac, 0x2e2d6d8b, 0x6e2b6d49, + 0x2e686ce6, 0x6e606ffe, 0x2eb36e51, 0x6ebd6f9b, + 0x0e3eafbc, 0x4e20affe, 0x0e69ad07, 0x4e6cad6a, + 0x0eb6aeb4, 0x4eacad6a, 0x0e66b4a4, 0x4e7ab738, + 0x0eb3b651, 0x4eb3b651, 0x0e3826f6, 0x4e252483, + 0x0e7f27dd, 0x4e71260f, 0x0eb826f6, 0x4eb52693, + 0x0eb5f693, 0x4eb8f6f6, 0x4ee4f462, 0x0ed1360f, + 0x4ec834e6, 0x2eaeedac, 0x6eb2ee30, 0x6eeded8b, + 0x2ecf2dcd, 0x6ed92f17, 0x0f81100f, 0x4f848862, + 0x4fc31841, 0x0fad518b, 0x4fa780c5, 0x4fd059ee, + 0x2fa890e6, 0x4fa38841, 0x6fc1900f, 0x0f7b8149, + 0x4f4688a4, 0x0faf81cd, 0x4fa58083, 0x0e3736d5, + 0x4e393717, 0x0e61341f, 0x4e7b3759, 0x0ea43462, + 0x4ea1341f, 0x4efd379b, 0x0e343e72, 0x4e2c3d6a, + 0x0e793f17, 0x4e753e93, 0x0ea53c83, 0x4eb43e72, + 0x4ee23c20, 0x2e3b8f59, 0x6e3c8f7a, 0x2e798f17, + 0x6e648c62, 0x2eb48e72, 0x6eae8dac, 0x6ee68ca4, + 0x2e3e37bc, 0x6e2037fe, 0x2e7f37dd, 0x6e723630, + 0x2ebd379b, 0x6ea834e6, 0x6eeb3549, 0x2e3f3fdd, + 0x6e343e72, 0x2e693d07, 0x6e663ca4, 0x2ea93d07, + 0x6eb13e0f, 0x6eeb3d49, 0x0e39e717, 0x4e2ae528, + 0x4e64e462, 0x2ebee7bc, 0x6eb7e6d5, 0x6ee1e41f, + 0x2e27e4c5, 0x6e3de79b, 0x6e62e420, 0x659239e8, + 0x65d03b94, 0x65d0232d, 0x65d120c2, 0x659129f2, + 0x65933ca3, 0x25969683, 0x25961d15, 0x254d1c48, + 0x259e3f61, 0x25953b96, 0x255b91d1, 0x247686ed, + 0x24309098, 0x2462edb9, 0x24a57468, 0xba5fd3e3, + 0x3a5f03e5, 0xfa411be4, 0x7a42cbe2, 0x93df03ff, + 0xc820ffff, 0x8822fc7f, 0xc8247cbf, 0x88267fff, + 0x4e010fe0, 0x5e040420, 0x4e081fe1, 0x4e0c1fe1, + 0x4e0a1fe1, 0x4e071fe1, 0x4e042c20, 0x4e062c20, + 0x4e052c20, 0x4e083c20, 0x0e0c3c20, 0x0e0a3c20, + 0x0e073c20, 0x9eae0020, 0x0f03f409, 0x6f03f40e, + 0x4cc0ac3f, 0x0ea1b820, 0x0ef9b820, 0x4ef9b820, + 0x4e21c862, 0x0e79c862, 0x4e79c862, 0x4e61b8a4, + 0x0e79b8a4, 0x4e79b8a4, 0x05a08020, 0x05104fe0, + 0x05505001, 0x05906fe2, 0x05d03005, 0x05101fea, + 0x05901feb, 0x04b0e3e0, 0x0470e7e1, 0x042f9c20, + 0x043f9c35, 0x047f9c20, 0x04ff9c20, 0x04299420, + 0x04319160, 0x0461943e, 0x04a19020, 0x04038100, + 0x040381a0, 0x040387e1, 0x04438be2, 0x04c38fe3, + 0x040181e0, 0x04018100, 0x04018621, 0x04418b22, + 0x04418822, 0x04818c23, 0x040081e0, 0x04008120, + 0x04008761, 0x04008621, 0x04408822, 0x04808c23, + 0x042053ff, 0x047f5401, 0x25208028, 0x2538cfe0, + 0x2578d001, 0x25b8efe2, 0x25f8f007, 0x2538dfea, + 0x25b8dfeb, 0xa400a3e0, 0xa420a7e0, 0xa4484be0, + 0xa467afe0, 0xa4a8a7ea, 0xa547a814, 0xa4084ffe, + 0xa55c53e0, 0xa5e1540b, 0xe400fbf6, 0xe408ffff, + 0xe420e7e0, 0xe4484be0, 0xe460efe0, 0xe547e400, + 0xe4014be0, 0xe4a84fe0, 0xe5f15000, 0x858043e0, + 0x85a043ff, 0xe59f5d08, 0x0420e3e9, 0x0460e3ea, + 0x04a0e3eb, 0x04e0e3ec, 0x25104042, 0x25104871, + 0x25904861, 0x25904c92, 0x05344020, 0x05744041, + 0x05b44062, 0x05f44083, 0x252c8840, 0x253c1420, + 0x25681572, 0x25a21ce3, 0x25ea1e34, 0x253c0421, + 0x25680572, 0x25a20ce3, 0x25ea0e34, 0x0522c020, + 0x05e6c0a4, 0x2401a001, 0x2443a051, 0x24858881, + 0x24c78cd1, 0x24850891, 0x24c70cc1, 0x250f9001, + 0x25508051, 0x25802491, 0x25df28c1, 0x25850c81, + 0x251e10d1, 0x65816001, 0x65c36051, 0x65854891, + 0x65c74cc1, 0x05733820, 0x05b238a4, 0x05f138e6, + 0x0570396a, 0x65d0a001, 0x65d6a443, 0x65d4a826, + 0x6594ac26, 0x6554ac26, 0x6556ac26, 0x6552ac26, + 0x65cbac85, 0x65caac01, 0x6589ac85, 0x6588ac01, + 0x65c9ac85, 0x65c8ac01, 0x65dea833, 0x659ca509, + 0x65d8a801, 0x65dcac01, 0x655cb241, 0x0520a1e0, + 0x0521a601, 0x052281e0, 0x05238601, 0x04a14026, + 0x042244a6, 0x046344a6, 0x04a444a6, 0x04e544a7, + 0x0568aca7, 0x05b23230, 0x853040af, 0xc5b040af, + 0xe57080af, 0xe5b080af, 0x25034440, 0x254054c4, + 0x25034640, 0x25415a05, 0x25834440, 0x25c54489, + 0x250b5d3a, 0x2550dc20, 0x2518e3e1, 0x2518e021, + 0x2518e0a1, 0x2518e121, 0x2518e1a1, 0x2558e3e2, + 0x2558e042, 0x2558e0c2, 0x2558e142, 0x2598e3e3, + 0x2598e063, 0x2598e0e3, 0x2598e163, 0x25d8e3e4, + 0x25d8e084, 0x25d8e104, 0x25d8e184, 0x2518e407, + 0x05214800, 0x05614800, 0x05a14800, 0x05e14800, + 0x05214c00, 0x05614c00, 0x05a14c00, 0x05e14c00, + 0x05304001, 0x05314001, 0x05a18610, 0x05e18610, + 0x05271e11, 0x6545e891, 0x6585e891, 0x65c5e891, + 0x6545c891, 0x6585c891, 0x65c5c891, 0x45b0c210, + 0x45f1c231, 0x1e601000, 0x1e603000, 0x1e621000, + 0x1e623000, 0x1e641000, 0x1e643000, 0x1e661000, + 0x1e663000, 0x1e681000, 0x1e683000, 0x1e6a1000, + 0x1e6a3000, 0x1e6c1000, 0x1e6c3000, 0x1e6e1000, + 0x1e6e3000, 0x1e701000, 0x1e703000, 0x1e721000, + 0x1e723000, 0x1e741000, 0x1e743000, 0x1e761000, + 0x1e763000, 0x1e781000, 0x1e783000, 0x1e7a1000, + 0x1e7a3000, 0x1e7c1000, 0x1e7c3000, 0x1e7e1000, + 0x1e7e3000, 0xf8268267, 0xf82d023c, 0xf8301046, + 0xf83d2083, 0xf8263290, 0xf82d528c, 0xf8284299, + 0xf8337160, 0xf8386286, 0xf8bf820e, 0xf8a600e0, + 0xf8af1353, 0xf8a922ea, 0xf8b53396, 0xf8a251e3, + 0xf8b340f4, 0xf8a470fd, 0xf8a06209, 0xf8f48097, + 0xf8f002ea, 0xf8eb10d9, 0xf8ff21b0, 0xf8f7302c, + 0xf8ee52a9, 0xf8f041fa, 0xf8e471e4, 0xf8e863c6, + 0xf864823d, 0xf87d013a, 0xf86f1162, 0xf87d20e3, + 0xf86132bb, 0xf870510e, 0xf8704336, 0xf86572b4, + 0xf8706217, 0xb83e8294, 0xb8200264, 0xb8381284, + 0xb8242358, 0xb8333102, 0xb828530e, 0xb83042df, + 0xb824703f, 0xb82a6194, 0xb8a080e9, 0xb8b80090, + 0xb8bb1146, 0xb8bb21b8, 0xb8b032df, 0xb8b653f4, + 0xb8bd41c9, 0xb8b47287, 0xb8bc6169, 0xb8ee828c, + 0xb8e10138, 0xb8f3126d, 0xb8f020b0, 0xb8e03183, + 0xb8e851ef, 0xb8f041e4, 0xb8fe7005, 0xb8ea6376, + 0xb8638120, 0xb873015d, 0xb8781284, 0xb86723b8, + 0xb86e3175, 0xb87b51ed, 0xb87f41d1, 0xb863721e, + 0xb87660f4, 0xce216874, 0xce104533, 0xce648c15, + 0xce8e3302, 0xce6e82ab, 0xce6c87d1, 0xcec08063, + 0xce638937, 0x25e0c358, 0x25a1c7d3, 0x0580785a, + 0x05426328, 0x05009892, 0x25a0cc29, 0x2561cec8, + 0x058044b3, 0x05401c99, 0x05006b49, 0x25e0d6f7, + 0x2561c528, 0x0583c8bc, 0x0542522f, 0x05001ec0, + 0x25e0de65, 0x25a1c113, 0x05803cad, 0x0540f3c0, + 0x0500ab15, 0x2560c28c, 0x2561d7c0, 0x05801ed7, + 0x0542633b, 0x05003696, 0x2560d4b4, 0x25e1c918, + 0x058021ff, 0x05400e15, 0x0500f3de, 0x0473025a, + 0x04bd05ab, 0x658e0025, 0x658a08e2, 0x659a0493, + 0x043e1062, 0x04f418b4, 0x046d15bd, 0x04611fce, + 0x04d6a07c, 0x04001929, 0x041a09da, 0x04d098f4, + 0x04db10d4, 0x0459a3ad, 0x041aa029, 0x041919fb, + 0x04d39e24, 0x04118302, 0x04101dba, 0x04d7ae16, + 0x04dea571, 0x04180210, 0x05e786fc, 0x05e4915c, + 0x04881cf1, 0x044a0f04, 0x04090969, 0x048b16c4, + 0x044101e4, 0x04dcbf44, 0x65809745, 0x658d833f, + 0x65c68468, 0x65c79b07, 0x65829e38, 0x049dafca, + 0x6582bba8, 0x65c0b7ff, 0x65c1b4e0, 0x658dbadd, + 0x65819a9d, 0x65ed9246, 0x65b30815, 0x65e6263c, + 0x65eebb94, 0x65bad14e, 0x65efe178, 0x65fc5697, + 0x65e07f14, 0x040c55a6, 0x04977f4d, 0x043d3046, + 0x04b733a0, 0x046830a4, 0x04ed322d, 0x05686948, + 0x05bd6c13, 0x65c88ef0, 0x450db3d7, 0x4540b6d9, + 0x043e3979, 0x445896ce, 0x445a9005, 0x44d98069, + 0x445b87ae, 0x04da348e, 0x04982edb, 0x0499397f, + 0x0408338c, 0x04ca309c, 0x65c721e6, 0x65c63641, + 0x65982882, 0x04812b8b, 0x0e251083, 0x4e3712d5, + 0x0e61101f, 0x4e6d118b, 0x0eba1338, 0x4eb712d5, + 0x2e31120f, 0x6e2e11ac, 0x2e6810e6, 0x6e6f11cd, + 0x2eaa1128, 0x6eb1120f, }; // END Generated code -- do not edit diff --git a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java index 76953bfb124..a4f40ccda92 100644 --- a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java +++ b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitAArch64.java @@ -33,9 +33,11 @@ * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 nop 7 * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 isb 3 * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 yield 1 + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c2 sb 1 * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 nop 7 * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 isb 3 - * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 yield + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 yield 1 + * @run driver compiler.onSpinWait.TestOnSpinWaitAArch64 c1 sb 1 */ package compiler.onSpinWait; @@ -50,13 +52,12 @@ public class TestOnSpinWaitAArch64 { public static void main(String[] args) throws Exception { String compiler = args[0]; String spinWaitInst = args[1]; - String spinWaitInstCount = (args.length == 3) ? args[2] : "1"; + String spinWaitInstCount = args[2]; ArrayList command = new ArrayList(); command.add("-XX:+IgnoreUnrecognizedVMOptions"); command.add("-showversion"); command.add("-XX:-BackgroundCompilation"); command.add("-XX:+UnlockDiagnosticVMOptions"); - command.add("-XX:+PrintAssembly"); if (compiler.equals("c2")) { command.add("-XX:-TieredCompilation"); } else if (compiler.equals("c1")) { @@ -69,12 +70,18 @@ public static void main(String[] args) throws Exception { command.add("-XX:OnSpinWaitInst=" + spinWaitInst); command.add("-XX:OnSpinWaitInstCount=" + spinWaitInstCount); command.add("-XX:CompileCommand=compileonly," + Launcher.class.getName() + "::" + "test"); + command.add("-XX:CompileCommand=print," + Launcher.class.getName() + "::" + "test"); command.add(Launcher.class.getName()); ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(command); OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + if ("sb".equals(spinWaitInst) && analyzer.contains("CPU does not support SB")) { + System.out.println("Skipping the test. The current CPU does not support SB instruction."); + return; + } + analyzer.shouldHaveExitValue(0); System.out.println(analyzer.getOutput()); @@ -89,6 +96,8 @@ private static String getSpinWaitInstHex(String spinWaitInst) { return "df3f 03d5"; } else if ("yield".equals(spinWaitInst)) { return "3f20 03d5"; + } else if ("sb".equals(spinWaitInst)) { + return "ff30 03d5"; } else { throw new RuntimeException("Unknown spin wait instruction: " + spinWaitInst); } From 839cede1a46b05d27abeaffbbd82c241910035cd Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Fri, 27 Jun 2025 14:06:12 +0000 Subject: [PATCH 206/213] 8357289: Break down the String constructor into smaller methods Reviewed-by: liach, rriggs --- .../share/classes/java/lang/String.java | 221 ++++++++---------- 1 file changed, 102 insertions(+), 119 deletions(-) diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 52af7dfd503..eac8a1355b7 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -553,135 +553,125 @@ public String(byte[] bytes, int offset, int length, Charset charset) { * disambiguate it against other similar methods of this class. */ private String(Charset charset, byte[] bytes, int offset, int length) { + String str; if (length == 0) { - this.value = "".value; - this.coder = "".coder; + str = ""; } else if (charset == UTF_8.INSTANCE) { - if (COMPACT_STRINGS) { - int dp = StringCoding.countPositives(bytes, offset, length); - if (dp == length) { - this.value = Arrays.copyOfRange(bytes, offset, offset + length); - this.coder = LATIN1; - return; + str = utf8(bytes, offset, length); + } else if (charset == ISO_8859_1.INSTANCE) { + str = iso88591(bytes, offset, length); + } else if (charset == US_ASCII.INSTANCE) { + str = ascii(bytes, offset, length); + } else { + str = decode(charset, bytes, offset, length); + } + this(str); + } + + private static String utf8(byte[] bytes, int offset, int length) { + if (COMPACT_STRINGS) { + int dp = StringCoding.countPositives(bytes, offset, length); + if (dp == length) { + return new String(Arrays.copyOfRange(bytes, offset, offset + length), LATIN1); + } + // Decode with a stable copy, to be the result if the decoded length is the same + byte[] latin1 = Arrays.copyOfRange(bytes, offset, offset + length); + int sp = dp; // first dp bytes are already in the copy + while (sp < length) { + int b1 = latin1[sp++]; + if (b1 >= 0) { + latin1[dp++] = (byte) b1; + continue; } - // Decode with a stable copy, to be the result if the decoded length is the same - byte[] latin1 = Arrays.copyOfRange(bytes, offset, offset + length); - int sp = dp; // first dp bytes are already in the copy - while (sp < length) { - int b1 = latin1[sp++]; - if (b1 >= 0) { - latin1[dp++] = (byte)b1; + if ((b1 & 0xfe) == 0xc2 && sp < length) { // b1 either 0xc2 or 0xc3 + int b2 = latin1[sp]; + if (b2 < -64) { // continuation bytes are always negative values in the range -128 to -65 + latin1[dp++] = (byte) decode2(b1, b2); + sp++; continue; } - if ((b1 & 0xfe) == 0xc2 && sp < length) { // b1 either 0xc2 or 0xc3 - int b2 = latin1[sp]; - if (b2 < -64) { // continuation bytes are always negative values in the range -128 to -65 - latin1[dp++] = (byte)decode2(b1, b2); - sp++; - continue; - } - } - // anything not a latin1, including the REPL - // we have to go with the utf16 - sp--; - break; - } - if (sp == length) { - if (dp != latin1.length) { - latin1 = Arrays.copyOf(latin1, dp); - } - this.value = latin1; - this.coder = LATIN1; - return; - } - byte[] utf16 = StringUTF16.newBytesFor(length); - StringLatin1.inflate(latin1, 0, utf16, 0, dp); - dp = decodeUTF8_UTF16(latin1, sp, length, utf16, dp, true); - if (dp != length) { - utf16 = Arrays.copyOf(utf16, dp << 1); } - this.value = utf16; - this.coder = UTF16; - } else { // !COMPACT_STRINGS - byte[] dst = StringUTF16.newBytesFor(length); - int dp = decodeUTF8_UTF16(bytes, offset, offset + length, dst, 0, true); - if (dp != length) { - dst = Arrays.copyOf(dst, dp << 1); + // anything not a latin1, including the REPL + // we have to go with the utf16 + sp--; + break; + } + if (sp == length) { + if (dp != latin1.length) { + latin1 = Arrays.copyOf(latin1, dp); } - this.value = dst; - this.coder = UTF16; + return new String(latin1, LATIN1); } - } else if (charset == ISO_8859_1.INSTANCE) { - if (COMPACT_STRINGS) { - this.value = Arrays.copyOfRange(bytes, offset, offset + length); - this.coder = LATIN1; - } else { - this.value = StringLatin1.inflate(bytes, offset, length); - this.coder = UTF16; + byte[] utf16 = StringUTF16.newBytesFor(length); + StringLatin1.inflate(latin1, 0, utf16, 0, dp); + dp = decodeUTF8_UTF16(latin1, sp, length, utf16, dp, true); + if (dp != length) { + utf16 = Arrays.copyOf(utf16, dp << 1); } - } else if (charset == US_ASCII.INSTANCE) { - if (COMPACT_STRINGS && !StringCoding.hasNegatives(bytes, offset, length)) { - this.value = Arrays.copyOfRange(bytes, offset, offset + length); - this.coder = LATIN1; - } else { - byte[] dst = StringUTF16.newBytesFor(length); - int dp = 0; - while (dp < length) { - int b = bytes[offset++]; - StringUTF16.putChar(dst, dp++, (b >= 0) ? (char) b : REPL); - } - this.value = dst; - this.coder = UTF16; + return new String(utf16, UTF16); + } else { // !COMPACT_STRINGS + byte[] dst = StringUTF16.newBytesFor(length); + int dp = decodeUTF8_UTF16(bytes, offset, offset + length, dst, 0, true); + if (dp != length) { + dst = Arrays.copyOf(dst, dp << 1); } + return new String(dst, UTF16); + } + } + + private static String iso88591(byte[] bytes, int offset, int length) { + if (COMPACT_STRINGS) { + return new String(Arrays.copyOfRange(bytes, offset, offset + length), LATIN1); } else { - // (1)We never cache the "external" cs, the only benefit of creating - // an additional StringDe/Encoder object to wrap it is to share the - // de/encode() method. These SD/E objects are short-lived, the young-gen - // gc should be able to take care of them well. But the best approach - // is still not to generate them if not really necessary. - // (2)The defensive copy of the input byte/char[] has a big performance - // impact, as well as the outgoing result byte/char[]. Need to do the - // optimization check of (sm==null && classLoader0==null) for both. - CharsetDecoder cd = charset.newDecoder(); - // ArrayDecoder fastpaths - if (cd instanceof ArrayDecoder ad) { - // ascii - if (ad.isASCIICompatible() && !StringCoding.hasNegatives(bytes, offset, length)) { - if (COMPACT_STRINGS) { - this.value = Arrays.copyOfRange(bytes, offset, offset + length); - this.coder = LATIN1; - return; - } - this.value = StringLatin1.inflate(bytes, offset, length); - this.coder = UTF16; - return; - } + return new String(StringLatin1.inflate(bytes, offset, length), UTF16); + } + } + + private static String ascii(byte[] bytes, int offset, int length) { + if (COMPACT_STRINGS && !StringCoding.hasNegatives(bytes, offset, length)) { + return new String(Arrays.copyOfRange(bytes, offset, offset + length), LATIN1); + } else { + byte[] dst = StringUTF16.newBytesFor(length); + int dp = 0; + while (dp < length) { + int b = bytes[offset++]; + StringUTF16.putChar(dst, dp++, (b >= 0) ? (char) b : REPL); + } + return new String(dst, UTF16); + } + } + private static String decode(Charset charset, byte[] bytes, int offset, int length) { + // (1)We never cache the "external" cs, the only benefit of creating + // an additional StringDe/Encoder object to wrap it is to share the + // de/encode() method. These SD/E objects are short-lived, the young-gen + // gc should be able to take care of them well. But the best approach + // is still not to generate them if not really necessary. + // (2)The defensive copy of the input byte/char[] has a big performance + // impact, as well as the outgoing result byte/char[]. Need to do the + // optimization check of (sm==null && classLoader0==null) for both. + CharsetDecoder cd = charset.newDecoder(); + // ArrayDecoder fastpaths + if (cd instanceof ArrayDecoder ad) { + // ascii + if (ad.isASCIICompatible() && !StringCoding.hasNegatives(bytes, offset, length)) { + return iso88591(bytes, offset, length); + } else { // fastpath for always Latin1 decodable single byte if (COMPACT_STRINGS && ad.isLatin1Decodable()) { byte[] dst = new byte[length]; ad.decodeToLatin1(bytes, offset, length, dst); - this.value = dst; - this.coder = LATIN1; - return; - } - - int en = scale(length, cd.maxCharsPerByte()); - cd.onMalformedInput(CodingErrorAction.REPLACE) - .onUnmappableCharacter(CodingErrorAction.REPLACE); - char[] ca = new char[en]; - int clen = ad.decode(bytes, offset, length, ca); - if (COMPACT_STRINGS) { - byte[] val = StringUTF16.compress(ca, 0, clen);; - this.coder = StringUTF16.coderFromArrayLen(val, clen); - this.value = val; - return; + return new String(dst, LATIN1); + } else { + int en = scale(length, cd.maxCharsPerByte()); + cd.onMalformedInput(CodingErrorAction.REPLACE) + .onUnmappableCharacter(CodingErrorAction.REPLACE); + char[] ca = new char[en]; + int clen = ad.decode(bytes, offset, length, ca); + return new String(ca, 0, clen, null); } - coder = UTF16; - value = StringUTF16.toBytes(ca, 0, clen); - return; } - + } else { // decode using CharsetDecoder int en = scale(length, cd.maxCharsPerByte()); cd.onMalformedInput(CodingErrorAction.REPLACE) @@ -694,14 +684,7 @@ private String(Charset charset, byte[] bytes, int offset, int length) { // Substitution is enabled, so this shouldn't happen throw new Error(x); } - if (COMPACT_STRINGS) { - byte[] val = StringUTF16.compress(ca, 0, caLen); - this.coder = StringUTF16.coderFromArrayLen(val, caLen); - this.value = val; - return; - } - coder = UTF16; - value = StringUTF16.toBytes(ca, 0, caLen); + return new String(ca, 0, caLen, null); } } From a471fe992fc0d71ba65b5fdbcc44b97a2783b90a Mon Sep 17 00:00:00 2001 From: Artur Barashev Date: Fri, 27 Jun 2025 14:15:55 +0000 Subject: [PATCH 207/213] 8360539: DTLS handshakes fails due to improper cookie validation logic Reviewed-by: ascarpino, hchao --- .../share/classes/sun/security/ssl/HelloCookieManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java index 5c2a09b7c03..b3155f5170a 100644 --- a/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java +++ b/src/java.base/share/classes/sun/security/ssl/HelloCookieManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -187,7 +187,7 @@ boolean isCookieValid(ServerHandshakeContext context, byte[] secret; d10ManagerLock.lock(); try { - if (((cookieVersion >> 24) & 0xFF) == cookie[0]) { + if ((byte) ((cookieVersion >> 24) & 0xFF) == cookie[0]) { secret = cookieSecret; } else { secret = legacySecret; // including out of window cookies From 12196baf6700d00c244747cfa22767e532a4a963 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Fri, 27 Jun 2025 14:54:12 +0000 Subject: [PATCH 208/213] 8358624: ImmutableDescriptor violates equals/hashCode contract after deserialization Reviewed-by: cjplummer, sspitsyn --- .../javax/management/ImmutableDescriptor.java | 6 ++ ...ImmutableDescriptorSerialHashCodeTest.java | 76 +++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 test/jdk/javax/management/descriptor/ImmutableDescriptorSerialHashCodeTest.java diff --git a/src/java.management/share/classes/javax/management/ImmutableDescriptor.java b/src/java.management/share/classes/javax/management/ImmutableDescriptor.java index ff90068958f..731dd619d26 100644 --- a/src/java.management/share/classes/javax/management/ImmutableDescriptor.java +++ b/src/java.management/share/classes/javax/management/ImmutableDescriptor.java @@ -138,6 +138,7 @@ private Object readResolve() throws InvalidObjectException { if (names == null || values == null || names.length != values.length) bad = true; if (!bad) { + hashCode = -1; // Force recalculation if (names.length == 0 && getClass() == ImmutableDescriptor.class) return EMPTY_DESCRIPTOR; final Comparator compare = String.CASE_INSENSITIVE_ORDER; @@ -441,12 +442,14 @@ public Descriptor clone() { */ public final void setFields(String[] fieldNames, Object[] fieldValues) throws RuntimeOperationsException { + if (fieldNames == null || fieldValues == null) illegal("Null argument"); if (fieldNames.length != fieldValues.length) illegal("Different array sizes"); for (int i = 0; i < fieldNames.length; i++) checkIllegalFieldName(fieldNames[i]); + hashCode = -1; // Force recalculation for (int i = 0; i < fieldNames.length; i++) setField(fieldNames[i], fieldValues[i]); } @@ -462,10 +465,12 @@ public final void setFields(String[] fieldNames, Object[] fieldValues) */ public final void setField(String fieldName, Object fieldValue) throws RuntimeOperationsException { + checkIllegalFieldName(fieldName); int i = fieldIndex(fieldName); if (i < 0) unsupported(); + hashCode = -1; // Force recalculation Object value = values[i]; if ((value == null) ? (fieldValue != null) : @@ -485,6 +490,7 @@ public final void setField(String fieldName, Object fieldValue) * be an {@link UnsupportedOperationException}. */ public final void removeField(String fieldName) { + hashCode = -1; // Force recalculation if (fieldName != null && fieldIndex(fieldName) >= 0) unsupported(); } diff --git a/test/jdk/javax/management/descriptor/ImmutableDescriptorSerialHashCodeTest.java b/test/jdk/javax/management/descriptor/ImmutableDescriptorSerialHashCodeTest.java new file mode 100644 index 00000000000..2fe8bf8034b --- /dev/null +++ b/test/jdk/javax/management/descriptor/ImmutableDescriptorSerialHashCodeTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8358624 + * @summary Test ImmutableDescriptor hashcode and serialization + * + * @run main ImmutableDescriptorSerialHashCodeTest + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import javax.management.Descriptor; +import javax.management.ImmutableDescriptor; + +public class ImmutableDescriptorSerialHashCodeTest { + public static void main(String[] args) throws Exception { + + Descriptor d1 = new ImmutableDescriptor("a=aval", "B=Bval", "cC=cCval"); + Descriptor d2 = new ImmutableDescriptor("a=aval", "B=Bval", "cC=cCval"); + + test (d1, d2, "Objects created from same String"); // Sanity check + Descriptor dSer = serialize(d1); + test(d1, dSer, "After serialization"); // Actual test + System.out.println("PASSED"); + } + + /** + * Test that two Descriptor objects are both equal, and have equal hashcodes. + */ + private static void test(Descriptor d1, Descriptor d2, String msg) throws Exception { + if (!d1.equals(d2)) { + throw new RuntimeException(msg + ": Descriptors not equal: " + + "\nd1: " + d1 + + "\nd2: " + d2); + } + if (d1.hashCode() != d2.hashCode()) { + throw new RuntimeException(msg + ": Hash code mismatch. hash1: " + d1.hashCode() + + ", hash2: " + d2.hashCode()); + } + } + + private static T serialize(T x) throws Exception { + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + ObjectOutputStream oout = new ObjectOutputStream(bout); + oout.writeObject(x); + oout.close(); + byte[] bytes = bout.toByteArray(); + ByteArrayInputStream bin = new ByteArrayInputStream(bytes); + ObjectInputStream oin = new ObjectInputStream(bin); + return (T) oin.readObject(); + } +} From 4edf791aecd432ecde00652acfaabddf136f4ca7 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 27 Jun 2025 16:11:41 +0000 Subject: [PATCH 209/213] 8295851: Do not use ttyLock in BytecodeTracer::trace Reviewed-by: dholmes, matsaave --- .../share/interpreter/bytecodeTracer.cpp | 46 +++++++++---------- .../runtime/interpreter/TraceBytecodes.java | 39 ++++++++++++++-- 2 files changed, 55 insertions(+), 30 deletions(-) diff --git a/src/hotspot/share/interpreter/bytecodeTracer.cpp b/src/hotspot/share/interpreter/bytecodeTracer.cpp index 798c0bfc7d8..1f912b2b00f 100644 --- a/src/hotspot/share/interpreter/bytecodeTracer.cpp +++ b/src/hotspot/share/interpreter/bytecodeTracer.cpp @@ -29,18 +29,14 @@ #include "interpreter/bytecodeTracer.hpp" #include "interpreter/bytecodes.hpp" #include "interpreter/interpreter.hpp" -#include "interpreter/interpreterRuntime.hpp" #include "memory/resourceArea.hpp" #include "oops/constantPool.inline.hpp" #include "oops/methodData.hpp" #include "oops/method.hpp" -#include "oops/resolvedFieldEntry.hpp" -#include "oops/resolvedIndyEntry.hpp" -#include "oops/resolvedMethodEntry.hpp" +#include "runtime/atomic.hpp" #include "runtime/handles.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/osThread.hpp" -#include "runtime/timer.hpp" #include "utilities/align.hpp" // Prints the current bytecode and its attributes using bytecode-specific information. @@ -85,10 +81,11 @@ class BytecodePrinter { void bytecode_epilog(int bci, outputStream* st); public: - BytecodePrinter(int flags = 0) { - _is_wide = false; - _code = Bytecodes::_illegal; - _flags = flags; + BytecodePrinter(int flags = 0) : _is_wide(false), _code(Bytecodes::_illegal), _flags(flags) {} + +#ifndef PRODUCT + BytecodePrinter(Method* prev_method) : BytecodePrinter(0) { + _current_method = prev_method; } // This method is called while executing the raw bytecodes, so none of @@ -96,6 +93,10 @@ class BytecodePrinter { void trace(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { ResourceMark rm; bool method_changed = _current_method != method(); + _current_method = method(); + _is_linked = method->method_holder()->is_linked(); + assert(_is_linked, "this function must be called on methods that are already executing"); + if (method_changed) { // Note 1: This code will not work as expected with true MT/MP. // Need an explicit lock or a different solution. @@ -107,9 +108,6 @@ class BytecodePrinter { st->print("[%zu] ", Thread::current()->osthread()->thread_id_for_printing()); method->print_name(st); st->cr(); - _current_method = method(); - _is_linked = method->method_holder()->is_linked(); - assert(_is_linked, "this function must be called on methods that are already executing"); } Bytecodes::Code code; if (is_wide()) { @@ -142,14 +140,13 @@ class BytecodePrinter { _is_wide = (code == Bytecodes::_wide); _code = Bytecodes::_illegal; -#ifndef PRODUCT if (TraceBytecodesStopAt != 0 && BytecodeCounter::counter_value() >= TraceBytecodesStopAt) { TraceBytecodes = false; } -#endif } +#endif - // Used for Method*::print_codes(). The input bcp comes from + // Used for Method::print_codes(). The input bcp comes from // BytecodeStream, which will skip wide bytecodes. void trace(const methodHandle& method, address bcp, outputStream* st) { _current_method = method(); @@ -179,19 +176,18 @@ class BytecodePrinter { }; #ifndef PRODUCT -// We need a global instance to keep track of the states when the bytecodes -// are executed. Access by multiple threads are controlled by ttyLocker. -static BytecodePrinter _interpreter_printer; +// We need a global instance to keep track of the method being printed so we can report that +// the method has changed. If this method is redefined and removed, that's ok because the method passed +// in won't match, and this will print the method passed in again. Racing threads changing this global +// will result in reprinting the method passed in again. +static Method* _method_currently_being_printed = nullptr; void BytecodeTracer::trace_interpreter(const methodHandle& method, address bcp, uintptr_t tos, uintptr_t tos2, outputStream* st) { if (TraceBytecodes && BytecodeCounter::counter_value() >= TraceBytecodesAt) { - ttyLocker ttyl; // 5065316: keep the following output coherent - // The ttyLocker also prevents races between two threads - // trying to use the single instance of BytecodePrinter. - // - // There used to be a leaf mutex here, but the ttyLocker will - // work just as well, as long as the printing operations never block. - _interpreter_printer.trace(method, bcp, tos, tos2, st); + BytecodePrinter printer(Atomic::load_acquire(&_method_currently_being_printed)); + printer.trace(method, bcp, tos, tos2, st); + // Save method currently being printed to detect when method printing changes. + Atomic::release_store(&_method_currently_being_printed, method()); } } #endif diff --git a/test/hotspot/jtreg/runtime/interpreter/TraceBytecodes.java b/test/hotspot/jtreg/runtime/interpreter/TraceBytecodes.java index b599f6c61ff..417e3a32b4b 100644 --- a/test/hotspot/jtreg/runtime/interpreter/TraceBytecodes.java +++ b/test/hotspot/jtreg/runtime/interpreter/TraceBytecodes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,13 +26,42 @@ * @bug 8309811 * @requires vm.debug * @summary Test the output of -XX:+TraceBytecodes, -XX:TraceBytecodesAt, and -XX:TraceBytecodesStopAt - * @run main/othervm -XX:+TraceBytecodes -XX:TraceBytecodesAt=2000 -XX:TraceBytecodesStopAt=3000 TraceBytecodes + * @run main/othervm -XX:+TraceBytecodes -XX:TraceBytecodesAt=1000000 -XX:TraceBytecodesStopAt=1001000 TraceBytecodes */ -// This is just a very simple sanity test. Trace about 1000 bytecodes. See the .jtr file for the output. +// CountBytecodes returns 1826384 bytecodes, so trace starting at a million to trace parallel threads. +// This is just a very simple sanity test. See the .jtr file for the output. // Consider it OK if the VM doesn't crash. It should test a fair amount of the code in bytecodeTracer.cpp -public class TraceBytecodes { - public static void main(String args[]) { +public class TraceBytecodes extends Thread { + public void run() { System.out.println("Hello TraceBytecodes"); } + + private static TraceBytecodes[] threads = new TraceBytecodes[2]; + private static boolean success = true; + + private static boolean report_success() { + for (int i = 0; i < 2; i++) { + try { + threads[i].join(); + } catch (InterruptedException e) {} + } + return success; + } + + public static void main(String args[]) { + threads[0] = new TraceBytecodes(); + threads[1] = new TraceBytecodes(); + for (int i = 0; i < 2; i++) { + threads[i].setName("Loading Thread #" + (i + 1)); + threads[i].start(); + System.out.println("Thread " + (i + 1) + " was started..."); + } + + if (report_success()) { + System.out.println("PASSED"); + } else { + throw new RuntimeException("FAILED"); + } + } } From da7080fffb2389465dc9afca6d02e9085fe15302 Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Fri, 27 Jun 2025 16:13:03 +0000 Subject: [PATCH 210/213] 8359761: JDK 25 RDP1 L10n resource files update Reviewed-by: aivanov, almatvee, nbenalla, jlu, dnguyen, cstein, naoto --- .../resources/swingset_de.properties | 12 +- .../launcher/resources/launcher_de.properties | 7 +- .../launcher/resources/launcher_ja.properties | 5 +- .../resources/launcher_zh_CN.properties | 5 +- .../keytool/resources/keytool_de.properties | 20 +-- .../keytool/resources/keytool_ja.properties | 28 ++-- .../resources/keytool_zh_CN.properties | 34 ++--- .../util/resources/auth_zh_CN.properties | 32 ++-- .../util/resources/security_ja.properties | 2 +- .../util/resources/security_zh_CN.properties | 14 +- .../impl/msg/XMLSchemaMessages_de.properties | 1 + .../impl/msg/XMLSchemaMessages_ja.properties | 1 + .../msg/XMLSchemaMessages_zh_CN.properties | 1 + .../internal/res/XPATHErrorResources_de.java | 10 +- .../internal/res/XPATHErrorResources_ja.java | 10 +- .../res/XPATHErrorResources_zh_CN.java | 10 +- .../javac/resources/compiler_de.properties | 141 +++++++++++++++++- .../javac/resources/compiler_ja.properties | 141 +++++++++++++++++- .../javac/resources/compiler_zh_CN.properties | 141 +++++++++++++++++- .../tools/javac/resources/javac_de.properties | 22 ++- .../tools/javac/resources/javac_ja.properties | 16 +- .../javac/resources/javac_zh_CN.properties | 16 +- .../javac/resources/launcher_de.properties | 7 +- .../javac/resources/launcher_ja.properties | 7 +- .../javac/resources/launcher_zh_CN.properties | 7 +- .../resources/serialver_de.properties | 2 +- .../resources/serialver_ja.properties | 2 +- .../resources/serialver_zh_CN.properties | 2 +- .../resources/jarsigner_de.properties | 65 ++++---- .../resources/jarsigner_ja.properties | 65 ++++---- .../resources/jarsigner_zh_CN.properties | 61 +++++--- .../sun/tools/jar/resources/jar_de.properties | 14 +- .../sun/tools/jar/resources/jar_ja.properties | 14 +- .../tools/jar/resources/jar_zh_CN.properties | 14 +- .../html/resources/standard_de.properties | 35 +++-- .../html/resources/standard_ja.properties | 35 +++-- .../html/resources/standard_zh_CN.properties | 35 +++-- .../toolkit/resources/doclets_de.properties | 18 ++- .../toolkit/resources/doclets_ja.properties | 14 +- .../resources/doclets_zh_CN.properties | 14 +- .../tool/resources/javadoc_de.properties | 4 +- .../tool/resources/javadoc_ja.properties | 4 +- .../tool/resources/javadoc_zh_CN.properties | 4 +- .../jconsole/resources/messages_de.properties | 2 +- .../example/debug/tty/TTYResources_de.java | 2 +- .../jimage/resources/jimage_de.properties | 68 +++++++++ .../jimage/resources/jimage_ja.properties | 68 +++++++++ .../jimage/resources/jimage_zh_CN.properties | 68 +++++++++ .../tools/jlink/resources/jlink_de.properties | 7 +- .../tools/jlink/resources/jlink_ja.properties | 3 +- .../jlink/resources/jlink_zh_CN.properties | 3 +- .../tools/jmod/resources/jmod_de.properties | 2 +- .../resources/LinuxResources_de.properties | 11 +- .../resources/LinuxResources_ja.properties | 11 +- .../resources/LinuxResources_zh_CN.properties | 11 +- .../resources/MacResources_de.properties | 14 +- .../resources/MacResources_ja.properties | 14 +- .../resources/MacResources_zh_CN.properties | 14 +- .../resources/HelpResources_de.properties | 2 +- .../resources/MainResources_de.properties | 23 ++- .../resources/MainResources_ja.properties | 23 ++- .../resources/MainResources_zh_CN.properties | 23 ++- .../resources/MsiInstallerStrings_de.wxl | 2 +- .../resources/MsiInstallerStrings_ja.wxl | 2 +- .../resources/MsiInstallerStrings_zh_CN.wxl | 2 +- .../resources/WinResources_de.properties | 5 +- .../resources/WinResources_ja.properties | 5 +- .../resources/WinResources_zh_CN.properties | 5 +- .../jshell/tool/resources/l10n_de.properties | 1 + .../jshell/tool/resources/l10n_ja.properties | 1 + .../tool/resources/l10n_zh_CN.properties | 1 + 71 files changed, 1103 insertions(+), 382 deletions(-) create mode 100644 src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_de.properties create mode 100644 src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_ja.properties create mode 100644 src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_zh_CN.properties diff --git a/src/demo/share/jfc/SwingSet2/resources/swingset_de.properties b/src/demo/share/jfc/SwingSet2/resources/swingset_de.properties index cd6de142a26..c5d1d682fe1 100644 --- a/src/demo/share/jfc/SwingSet2/resources/swingset_de.properties +++ b/src/demo/share/jfc/SwingSet2/resources/swingset_de.properties @@ -456,13 +456,13 @@ SliderDemo.horizontal=Horizontal SliderDemo.vertical=Vertikal SliderDemo.plain=Einfach SliderDemo.a_plain_slider=Ein einfacher Schieberegler -SliderDemo.majorticks=Grobteilungen -SliderDemo.majorticksdescription=Ein Schieberegler mit Grobteilungsmarkierungen -SliderDemo.ticks=Feinteilungen, Teilungen zum Einrasten und Labels -SliderDemo.minorticks=Feinteilungen -SliderDemo.minorticksdescription=Ein Schieberegler mit Grob- und Feinteilungen, mit Teilungen, in die der Schieberegler einrastet, wobei einige Teilungen mit einem sichtbaren Label versehen sind +SliderDemo.majorticks=Hauptteilstriche +SliderDemo.majorticksdescription=Ein Schieberegler mit Hauptteilstrichen +SliderDemo.ticks=Hilfsteilstriche, zum Einrasten und Beschriften +SliderDemo.minorticks=Hilfsteilstriche +SliderDemo.minorticksdescription=Ein Schieberegler mit Haupt- und Hilfsteilstrichen, in die der Schieberegler einrastet, wobei einige Teilstriche mit einer sichtbaren Beschriftung versehen sind SliderDemo.disabled=Deaktiviert -SliderDemo.disableddescription=Ein Schieberegler mit Grob- und Feinteilungen, der nicht aktiviert ist (kann nicht bearbeitet werden) +SliderDemo.disableddescription=Ein Schieberegler mit Haupt- und Hilfsteilstrichen, der nicht aktiviert ist (kann nicht bearbeitet werden) ### SplitPane Demo ### diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties index 1f922b4cf73..79b5968b210 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,8 @@ java.launcher.opt.footer = \ -cp ...|:]\n -disableassertions[:...|:]\n Deaktiviert Assertions mit angegebener Granularität\n -esa | -enablesystemassertions\n Aktiviert System-Assertions\n -dsa | -disablesystemassertions\n Deaktiviert System-Assertions\n -agentlib:[=]\n Lädt die native Agent Library . Beispiel: -agentlib:jdwp\n siehe auch -agentlib:jdwp=help\n -agentpath:[=]\n Lädt die native Agent Library mit dem vollständigen Pfadnamen\n -javaagent:[=]\n Lädt den Java-Programmiersprachen-Agent, siehe java.lang.instrument\n -splash:\n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch unterstützt und verwendet,\n falls verfügbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" übergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgewählt.\n Weitere Informationen finden Sie in der Dokumentation zur SplashScreen-API\n @argument files\n Eine oder mehrere Argumentdateien mit Optionen\n --disable-@files\n Verhindert die weitere Erweiterung von Argumentdateien\n --enable-preview\n Lässt zu, das Klassen von Vorschaufeatures dieses Release abhängig sind\nUm ein Argument für eine lange Option anzugeben, können Sie --= oder\n-- verwenden.\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:\n An das Ende des Bootstrap Classpaths anhängen\n -Xcheck:jni Führt zusätzliche Prüfungen für JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Führt keine Aktion aus. Ist veraltet und wird in einem zukünftigen Release entfernt.\n -Xdiag Zeigt zusätzliche Diagnosemeldungen an\n -Xint Nur Ausführung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog: Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n für weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausführung im gemischten Modus (Standard)\n -Xmn Legt die anfängliche und maximale Größe (in Byte) des Heaps\n für die Young Generation (Nursery) fest\n -Xms Legt die anfängliche Java-Heap-Größe fest\n -Xmx Legt die maximale Java-Heap-Größe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn möglich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verläuft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern führen. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und fährt fort\n -XshowSettings:all\n Zeigt alle Einstellungen als Verbose-Ausgabe an und fährt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und fährt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und fährt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und fährt fort\n -XshowSettings:security\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:all\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:properties\n Zeigt Sicherheitseigenschaften an und fährt fort\n -XshowSettings:security:providers\n Zeigt statische Sicherheitsprovidereinstellungen an und fährt fort\n -XshowSettings:security:tls\n Zeigt TLS-bezogene Sicherheitseinstellungen an und fährt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und fährt fort\n -Xss Legt die Stackgröße des Java-Threads fest\n Die tatsächliche Größe kann auf ein Vielfaches der\n Systemseitengröße aufgerundet werden, wenn für das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n \ - Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zukünftigen Release entfernt werden kann.\n --add-reads =(,)*\n Aktualisiert , damit gelesen wird, ungeachtet\n der Moduldeklaration. \n kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um in zu exportieren,\n ungeachtet der Moduldeklaration.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um in\n zu öffnen, ungeachtet der Moduldeklaration.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n Überschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source \n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist entweder "enabled" oder "disabled".\n Die Finalisierung ist standardmäßig aktiviert.\n --sun-misc-unsafe-memory-access=\n Verwendung der nicht unterstützten API sun.misc.Unsafe zulassen oder verweigern\n ist "allow", "warn", "debug" oder "deny".\n Der Standardwert ist "warn".\n\nDiese zusätzlichen Optionen können jederzeit ohne vorherige Ankündigung geändert werden.\n +java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:\n An das Ende des Bootstrap Classpaths anhängen\n -Xcheck:jni Führt zusätzliche Prüfungen für JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Führt keine Aktion aus. Ist veraltet und wird in einem zukünftigen Release entfernt.\n -Xdiag Zeigt zusätzliche Diagnosemeldungen an\n -Xint Nur Ausführung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog: Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n für weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausführung im gemischten Modus (Standard)\n -Xmn Legt die anfängliche und maximale Größe (in Byte) des Heaps\n für die Young Generation (Nursery) fest\n -Xms Legt die minimale und die anfängliche Java-Heap-Größe fest\n -Xmx Legt die maximale Java-Heap-Größe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn möglich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verläuft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern führen. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und fährt fort\n -XshowSettings:all\n Zeigt alle Einstellungen als Verbose-Ausgabe an und fährt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und fährt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und fährt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und fährt fort\n -XshowSettings:security\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:all\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:properties\n Zeigt Sicherheitseigenschaften an und fährt fort\n -XshowSettings:security:providers\n Zeigt statische Sicherheitsprovidereinstellungen an und fährt fort\n -XshowSettings:security:tls\n Zeigt TLS-bezogene Sicherheitseinstellungen an und fährt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und fährt fort\n -Xss Legt die Stackgröße des Java-Threads fest\n Die tatsächliche Größe kann auf ein Vielfaches der\n Systemseitengröße aufgerundet werden, wenn für das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n \ + Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zukünftigen Release entfernt werden kann.\n --add-reads =(,)*\n Aktualisiert , damit gelesen wird, ungeachtet\n der Moduldeklaration. \n kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um in zu exportieren,\n ungeachtet der Moduldeklaration.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um in\n zu öffnen, ungeachtet der Moduldeklaration.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n Überschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source \n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist entweder "enabled" oder "disabled".\n Die Finalisierung ist standardmäßig aktiviert.\n --sun-misc-unsafe-memory-access=\n Verwendung der nicht unterstützten API sun.misc.Unsafe zulassen oder verweigern\n ist "allow", "warn", "debug" oder "deny".\n Der Standardwert ist "warn".\n\nDiese zusätzlichen Optionen können jederzeit ohne vorherige Ankündigung geändert werden.\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\nDie folgenden Optionen sind für macOS spezifisch:\n -XstartOnFirstThread\n Führt die main()-Methode für den ersten (AppKit-)Thread aus\n -Xdock:name=\n Setzt den im Dock angezeigten Standardanwendungsnamen außer Kraft\n -Xdock:icon=\n Setzt das im Dock angezeigte Standardsymbol außer Kraft\n\n @@ -51,6 +51,7 @@ java.launcher.cls.error4=Fehler: Beim Laden der Klasse {0} ist ein LinkageError java.launcher.cls.error5=Fehler: Hauptklasse {0} kann nicht initialisiert werden\nUrsache: {1}: {2} java.launcher.cls.error6=Fehler: Kein nicht privater Null-Argument-Konstruktor in Klasse {0} gefunden\nEntfernen Sie die Eigenschaft "private" aus dem vorhandenen Konstruktor, oder definieren Sie ihn als:\n public {0}() java.launcher.cls.error7=Fehler: Konstruktor mit nicht statischer innerer Klasse {0} kann nicht aufgerufen werden \nLegen Sie die innere Klasse als statisch fest, oder verschieben Sie sie in eine separate Quelldatei +java.launcher.cls.error8=Fehler: Abstrakte Klasse {0} kann nicht instanziiert werden.\nVerwenden Sie eine konkrete Klasse java.launcher.jar.error1=Fehler: Beim Versuch, Datei {0} zu öffnen, ist ein unerwarteter Fehler aufgetreten java.launcher.jar.error2=Manifest in {0} nicht gefunden java.launcher.jar.error3=kein Hauptmanifestattribut, in {0} diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties index c6f1b8b330a..04b68db3a8e 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ java.launcher.opt.footer = \ -cp <ディレクトリおよびzip/jarファイ -disableassertions[:...|:]\n 指定した粒度でアサーションを無効にします\n -esa | -enablesystemassertions\n システム・アサーションを有効にします\n -dsa | -disablesystemassertions\n システム・アサーションを無効にします\n -agentlib:[=]\n ネイティブ・エージェント・ライブラリをロードします。例: -agentlib:jdwp\n -agentlib:jdwp=helpも参照してください\n -agentpath:[=]\n フルパス名を使用して、ネイティブ・エージェント・ライブラリをロードします\n -javaagent:[=]\n Javaプログラミング言語エージェントをロードします。java.lang.instrumentを参照してください\n -splash:\n 指定されたイメージを含むスプラッシュ画面を表示します\n HiDPIスケールのイメージが自動的にサポートされて使用されます\n (可能な場合)。スケーリングされないイメージのファイル名(image.extなど)を\n 引数として-splashオプションに必ず渡す必要があります。\n 指定された最も適切なスケーリング済イメージが選択されます\n (自動的)。\n 詳細は、SplashScreen APIのドキュメントを参照してください\n @argumentファイル\n オプションを含む1つ以上の引数ファイル\n --disable-@files\n さらなる引数ファイル拡張を無効にします\n --enable-preview\n クラスをこのリリースのプレビュー機能に依存させることができます\n長いオプションの引数を指定する場合、--=または\n-- を使用できます。\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch バックグラウンド・コンパイルを無効にします\n -Xbootclasspath/a:\n ブートストラップ・クラス・パスの最後に追加します\n -Xcheck:jni JNI関数に対する追加のチェックを実行します\n -Xcomp 初回呼出し時にメソッドのコンパイルを強制します\n -Xdebug 何も実行されません。将来のリリースで削除されるため、非推奨になりました。\n -Xdiag 追加の診断メッセージを表示します\n -Xint インタプリタ・モードの実行のみ\n -Xinternalversion\n -versionオプションより詳細なJVMバージョン情報を\n 表示します\n -Xlog: Java Virtual Machine (JVM)統合ロギング・フレームワークでの\n ロギングを構成または有効化します。詳細は、-Xlog:helpを\n 使用してください。\n -Xloggc: タイムスタンプが付いたファイルにGCステータスのログを記録します\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。-Xlog:gc:で置換されています。\n -Xmixed 混合モードの実行(デフォルト)\n -Xmn 若い世代(ナーサリ)のヒープの初期サイズおよび最大サイズ\n (バイト単位)を設定します\n -Xms Javaの初期ヒープ・サイズを設定します\n -Xmx Javaの最大ヒープ・サイズを設定します\n -Xnoclassgc クラスのガベージ・コレクションを無効にします\n -Xrs Java/VMによるOSシグナルの使用を削減します(ドキュメントを参照)\n -Xshare:auto 可能であれば共有クラス・データを使用します(デフォルト)\n -Xshare:off 共有クラス・データの使用を試みません\n -Xshare:on 共有クラス・データの使用を必須にし、できなければ失敗します。\n \ +java.launcher.X.usage=\n -Xbatch バックグラウンド・コンパイルを無効にします\n -Xbootclasspath/a:\n ブートストラップ・クラス・パスの最後に追加します\n -Xcheck:jni JNI関数に対する追加のチェックを実行します\n -Xcomp 初回呼出し時にメソッドのコンパイルを強制します\n -Xdebug 何も実行されません。将来のリリースで削除されるため、非推奨になりました。\n -Xdiag 追加の診断メッセージを表示します\n -Xint インタプリタ・モードの実行のみ\n -Xinternalversion\n -versionオプションより詳細なJVMバージョン情報を\n 表示します\n -Xlog: Java Virtual Machine (JVM)統合ロギング・フレームワークでの\n ロギングを構成または有効化します。詳細は、-Xlog:helpを\n 使用してください。\n -Xloggc: タイムスタンプが付いたファイルにGCステータスのログを記録します\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。-Xlog:gc:で置換されています。\n -Xmixed 混合モードの実行(デフォルト)\n -Xmn 若い世代(ナーサリ)のヒープの初期サイズおよび最大サイズ\n (バイト単位)を設定します\n -Xms Javaの最小および初期のヒープ・サイズを設定します\n -Xmx Javaの最大ヒープ・サイズを設定します\n -Xnoclassgc クラスのガベージ・コレクションを無効にします\n -Xrs Java/VMによるOSシグナルの使用を削減します(ドキュメントを参照)\n -Xshare:auto 可能であれば共有クラス・データを使用します(デフォルト)\n -Xshare:off 共有クラス・データの使用を試みません\n -Xshare:on 共有クラス・データの使用を必須にし、できなければ失敗します。\n \ これはテスト・オプションであり、断続的な失敗につながる\n 可能性があります。本番環境では使用しないでください。\n -XshowSettings すべての設定を表示して続行します\n -XshowSettings:all\n すべての設定を詳細に表示して続行します\n -XshowSettings:locale\n すべてのロケール関連の設定を表示して続行します\n -XshowSettings:properties\n すべてのプロパティ設定を表示して続行します\n -XshowSettings:vm\n すべてのVM関連の設定を表示して続行します\n -XshowSettings:security\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:all\n すべてのセキュリティ設定を表示して続行します\n -XshowSettings:security:properties\n セキュリティ・プロパティを表示して続行します\n -XshowSettings:security:providers\n 静的セキュリティ・プロバイダ設定を表示して続行します\n -XshowSettings:security:tls\n TLS関連のセキュリティ設定を表示して続行します\n -XshowSettings:system\n (Linuxのみ)ホスト・システムまたはコンテナを表示します\n 構成して続行します\n -Xss javaスレッドのスタック・サイズを設定します\n 実際のサイズは、次の倍数に切り上げられる場合があります: \n オペレーティング・システムの要件に応じたシステム・ページ・サイズ。\n -Xverify バイトコード・ベリファイアのモードを設定します\n オプション-Xverify:noneは非推奨になり、\n 将来のリリースで削除される可能性があります。\n --add-reads =(,)*\n モジュール宣言に関係なく、を更新してを\n 読み取ります。 \n をALL-UNNAMEDに設定すると、すべての名前のないモジュールを\n 読み取ることができます。\n --add-exports \ /=(,)*\n モジュール宣言に関係なく、を更新してに\n エクスポートします。\n をALL-UNNAMEDに設定すると、すべての名前のないモジュールに\n エクスポートできます。\n --add-opens /=(,)*\n モジュール宣言に関係なく、を更新してを\n に開きます。\n --limit-modules [,...]\n 参照可能なモジュールの領域を制限します\n --patch-module =({0})*\n JARファイルまたはディレクトリのクラスおよびリソースで\n モジュールをオーバーライドまたは拡張します。\n --source \n ソースファイル・モードでソースのバージョンを設定します。\n --finalization=\n JVMがオブジェクトのファイナライズを実行するかどうかを制御します\n は"enabled"または"disabled"のいずれかです。\n ファイナライズはデフォルトで有効になっています。\n --sun-misc-unsafe-memory-access=\n サポートされていないAPI sun.misc.Unsafeの使用を許可または拒否します\n は"allow"、"warn"、"debug"または"deny"のいずれかです。\n デフォルト値は"warn"です。\n\nこの追加オプションは予告なしに変更されることがあります。\n @@ -53,6 +53,7 @@ java.launcher.cls.error4=エラー: メイン・クラス{0}のロード中にLi java.launcher.cls.error5=エラー: メイン・クラス{0}を初期化できません\n原因: {1}: {2} java.launcher.cls.error6=エラー: 非privateのゼロ引数コンストラクタがクラス{0}に見つかりません\n既存のコンストラクタからprivateを削除するか、次のように定義してください:\n public {0}() java.launcher.cls.error7=エラー: staticでない内部クラス{0}コンストラクタを起動できません \n内部クラスをstaticにするか、内部クラスを外部に出してソース・ファイルを区別してください +java.launcher.cls.error8=エラー: 抽象クラス{0}はインスタンス化できません\n具象クラスを使用してください java.launcher.jar.error1=エラー: ファイル{0}を開こうとしているときに、予期しないエラーが発生しました java.launcher.jar.error2={0}にマニフェストが見つかりません java.launcher.jar.error3={0}にメイン・マニフェスト属性がありません diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties index 56d774b47db..ec466bf3019 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ java.launcher.opt.footer = \ -cp <目录和 zip/jar 文件的类搜索路径> 将产品版本输出到输出流并退出\n -showversion 将产品版本输出到错误流并继续\n --show-version\n 将产品版本输出到输出流并继续\n --show-module-resolution\n 在启动过程中显示模块解析输出\n -? -h -help\n 将此帮助消息输出到错误流\n --help 将此帮助消息输出到输出流\n -X 将额外选项的帮助输出到错误流\n --help-extra 将额外选项的帮助输出到输出流\n -ea[:<程序包名称>...|:<类名>]\n -enableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度启用断言\n -da[:<程序包名称>...|:<类名>]\n -disableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度禁用断言\n -esa | -enablesystemassertions\n 启用系统断言\n -dsa | -disablesystemassertions\n 禁用系统断言\n -agentlib:<库名>[=<选项>]\n 加载本机代理库 <库名>, 例如 -agentlib:jdwp\n 另请参阅 -agentlib:jdwp=help\n -agentpath:<路径名>[=<选项>]\n 按完整路径名加载本机代理库\n -javaagent:[=<选项>]\n 加载 Java 编程语言代理, 请参阅 java.lang.instrument\n -splash:<图像路径>\n 使用指定的图像显示启动屏幕\n 自动支持和使用 HiDPI 缩放图像\n (如果可用)。应始终将未缩放的图像文件名 (例如, image.ext)\n 作为参数传递给 -splash 选项。\n 将自动选取提供的最合适的缩放\n 图像。\n 有关详细信息, 请参阅 SplashScreen API 文档\n @argument 文件\n 一个或多个包含选项的参数文件\n --disable-@files\n 阻止进一步扩展参数文件\n --enable-preview\n 允许类依赖于此发行版的预览功能\n要为长选项指定参数, 可以使用 --<名称>=<值> 或\n--<名称> <值>。\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch 禁用后台编译\n -Xbootclasspath/a:<以 {0} 分隔的目录和 zip/jar 文件>\n 附加在引导类路径末尾\n -Xcheck:jni 对 JNI 函数执行其他检查\n -Xcomp 强制在首次调用时编译方法\n -Xdebug 不执行任何操作;已过时,将在未来发行版中删除。\n -Xdiag 显示附加诊断消息\n -Xint 仅解释模式执行\n -Xinternalversion\n 显示比 -version 选项更详细的\n JVM 版本信息\n -Xlog: 配置或启用采用 Java 虚拟\n 机 (Java Virtual Machine, JVM) 统一记录框架进行事件记录。使用 -Xlog:help\n 可了解详细信息。\n -Xloggc: 将 GC 状态记录在文件中(带时间戳)。\n 此选项已过时,可能会在\n 将来的发行版中删除。它将替换为 -Xlog:gc:。\n -Xmixed 混合模式执行(默认值)\n -Xmn 为年轻代(新生代)设置初始和最大堆大小\n (以字节为单位)\n -Xms 设置初始 Java 堆大小\n -Xmx 设置最大 Java 堆大小\n -Xnoclassgc 禁用类垃圾收集\n -Xrs 减少 Java/VM 对操作系统信号的使用(请参见文档)\n -Xshare:auto 在可能的情况下使用共享类数据(默认值)\n -Xshare:off 不尝试使用共享类数据\n -Xshare:on 要求使用共享类数据,否则将失败。\n 这是一个测试选项,可能导致间歇性\n 故障。不应在生产环境中使用它。\n -XshowSettings 显示所有设置并继续\n -XshowSettings:all\n 详细显示所有设置并继续\n -XshowSettings:locale\n 显示所有与区域设置相关的设置并继续\n -XshowSettings:properties\n 显示所有属性设置并继续\n -XshowSettings:vm\n 显示所有与 vm 相关的设置并继续\n -XshowSettings:security\n 显示所有安全设置并继续\n -XshowSettings:security:all\n 显示所有安全设置并继续\n -XshowSettings:security:properties\n 显示安全属性并继续\n -XshowSettings:security:providers\n 显示静态安全提供方设置并继续\n -XshowSettings:security:tls\n 显示与 TLS \ +java.launcher.X.usage=\n -Xbatch 禁用后台编译\n -Xbootclasspath/a:<以 {0} 分隔的目录和 zip/jar 文件>\n 附加在引导类路径末尾\n -Xcheck:jni 对 JNI 函数执行其他检查\n -Xcomp 强制在首次调用时编译方法\n -Xdebug 不执行任何操作;已过时,将在未来发行版中删除。\n -Xdiag 显示附加诊断消息\n -Xint 仅解释模式执行\n -Xinternalversion\n 显示比 -version 选项更详细的\n JVM 版本信息\n -Xlog: 配置或启用采用 Java 虚拟\n 机 (Java Virtual Machine, JVM) 统一记录框架进行事件记录。使用 -Xlog:help\n 可了解详细信息。\n -Xloggc: 将 GC 状态记录在文件中(带时间戳)。\n 此选项已过时,可能会在\n 将来的发行版中删除。它将替换为 -Xlog:gc:。\n -Xmixed 混合模式执行(默认值)\n -Xmn 为年轻代(新生代)设置初始和最大堆大小\n (以字节为单位)\n -Xms 设置最小和初始 Java 堆大小\n -Xmx 设置最大 Java 堆大小\n -Xnoclassgc 禁用类垃圾收集\n -Xrs 减少 Java/VM 对操作系统信号的使用(请参见文档)\n -Xshare:auto 在可能的情况下使用共享类数据(默认值)\n -Xshare:off 不尝试使用共享类数据\n -Xshare:on 要求使用共享类数据,否则将失败。\n 这是一个测试选项,可能导致间歇性\n 故障。不应在生产环境中使用它。\n -XshowSettings 显示所有设置并继续\n -XshowSettings:all\n 详细显示所有设置并继续\n -XshowSettings:locale\n 显示所有与区域设置相关的设置并继续\n -XshowSettings:properties\n 显示所有属性设置并继续\n -XshowSettings:vm\n 显示所有与 vm 相关的设置并继续\n -XshowSettings:security\n 显示所有安全设置并继续\n -XshowSettings:security:all\n 显示所有安全设置并继续\n -XshowSettings:security:properties\n 显示安全属性并继续\n -XshowSettings:security:providers\n 显示静态安全提供方设置并继续\n -XshowSettings:security:tls\n 显示与 TLS \ 相关的安全设置并继续\n -XshowSettings:system\n (仅 Linux)显示主机系统或容器\n 配置并继续\n -Xss 设置 Java 线程堆栈大小\n 实际大小可以舍入到\n 操作系统要求的系统页面大小的倍数。\n -Xverify 设置字节码验证器的模式\n 请注意,选项 -Xverify:none 已过时,\n 可能会在未来发行版中删除。\n --add-reads =(,)*\n 更新 以读取 ,而无论\n 模块如何声明。 \n 可以是 ALL-UNNAMED,将读取所有未命名\n 模块。\n --add-exports /=(,)*\n 更新 以将 导出到 ,\n 而无论模块如何声明。\n 可以是 ALL-UNNAMED,将导出到所有\n 未命名模块。\n --add-opens /=(,)*\n 更新 以在 中打开\n ,而无论模块如何声明。\n --limit-modules [,...]\n 限制可观察模块的领域\n --patch-module =({0})*\n 使用 JAR 文件或目录中的类和资源\n 覆盖或增强模块。\n --source \n 设置源文件模式中源的版本。\n --finalization=\n 控制 JVM 是否执行对象最终处理,\n 其中 为 "enabled" 或 "disabled" 之一。\n 默认情况下,最终处理处于启用状态。\n --sun-misc-unsafe-memory-access=\n 允许或拒绝使用不受支持的 API sun.misc.Unsafe\n 为 "allow"、"warn"、"debug" 或 "deny" 之一。\n 默认值为 "warn"。\n\n这些额外选项如有更改, 恕不另行通知。\n # Translators please note do not translate the options themselves @@ -51,6 +51,7 @@ java.launcher.cls.error4=错误: 加载主类 {0} 时出现 LinkageError\n\t{1} java.launcher.cls.error5=错误: 无法初始化主类 {0}\n原因: {1}: {2} java.launcher.cls.error6=错误:在类 {0} 中未找到非专用零参数构造器\n请从现有构造器中删除专用,或者定义为:\n public {0}() java.launcher.cls.error7=错误:无法调用非静态内部类 {0} 构造器\n请将内部类设为静态或将内部类移出到单独的源文件 +java.launcher.cls.error8=错误:无法实例化抽象类 {0}\n请使用具体类 java.launcher.jar.error1=错误: 尝试打开文件{0}时出现意外错误 java.launcher.jar.error2=在{0}中找不到清单 java.launcher.jar.error3={0}中没有主清单属性 diff --git a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties index 6290bb2a7ac..1c7a9cd17cf 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties +++ b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties @@ -27,7 +27,7 @@ NEWLINE=\n STAR=******************************************* STARNN=*******************************************\n\n # keytool: Help part -.OPTION.=\u0020[OPTION]... +.OPTION.=\ [OPTION]... Options.=Optionen: option.1.set.twice=Die Option %s wurde mehrmals angegeben. Alle Angaben bis auf die letzte werden ignoriert. multiple.commands.1.2=Nur ein Befehl ist zulässig: Sowohl %1$s als auch %2$s wurden angegeben. @@ -170,7 +170,7 @@ Certificate.reply.was.installed.in.keystore=Zertifikatsantwort wurde in Keystore Certificate.reply.was.not.installed.in.keystore=Zertifikatsantwort wurde nicht in Keystore installiert Certificate.was.added.to.keystore=Zertifikat wurde Keystore hinzugefügt Certificate.was.not.added.to.keystore=Zertifikat wurde nicht zu Keystore hinzugefügt -.Storing.ksfname.=[{0} wird gesichert] +.Storing.ksfname.=[{0} wird gespeichert] alias.has.no.public.key.certificate.={0} hat keinen Public Key (Zertifikat) Cannot.derive.signature.algorithm=Signaturalgorithmus kann nicht abgeleitet werden Alias.alias.does.not.exist=Alias <{0}> ist nicht vorhanden @@ -178,9 +178,9 @@ Alias.alias.has.no.certificate=Alias <{0}> hat kein Zertifikat groupname.keysize.coexist=Es können nicht sowohl -groupname als auch -keysize angegeben werden deprecate.keysize.for.ec=Das Angeben von -keysize zum Generieren von EC-Schlüsseln ist veraltet. Verwenden Sie stattdessen "-groupname %s". Key.pair.not.generated.alias.alias.already.exists=Schlüsselpaar wurde nicht generiert. Alias <{0}> ist bereits vorhanden -size.bit.alg=%1$d-Bit %2$s -Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=Schlüsselpaar {0} und selbstsigniertes Zertifikat ({1}) werden mit einer Gültigkeit von {2} Tagen generiert\n\tfür: {3} -Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=Schlüsselpaar {0} und Zertifikat ({1}) werden generiert, das von <{2}> mit einer Gültigkeit von {3} Tagen ausgestellt wurde\n\tfür: {4} +size.bit.alg=%1$d-Bit-%2$s +Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=Generieren von {0}-Schlüsselpaar und selbstsigniertem Zertifikat ({1}) mit einer Gültigkeit von {2} Tagen\n\tfür: {3} +Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=Generieren von {0}-Schlüsselpaar und einem von <{2}> ausgestellten Zertifikat ({1}) mit einer Gültigkeit von {3} Tagen\n\tfür: {4} Enter.key.password.for.alias.=Schlüsselkennwort für <{0}> eingeben .RETURN.if.same.as.keystore.password.=\t(RETURN, wenn identisch mit Keystore-Kennwort): \u0020 Key.password.is.too.short.must.be.at.least.6.characters=Schlüsselkennwort ist zu kurz. Es muss mindestens sechs Zeichen lang sein @@ -216,7 +216,7 @@ Do.you.still.want.to.add.it.no.=Möchten Sie es trotzdem hinzufügen? [Nein]: \u Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias.=Zertifikat ist bereits unter Alias <{0}> im systemweiten CA-Keystore vorhanden Do.you.still.want.to.add.it.to.your.own.keystore.no.=Möchten Sie es trotzdem zu Ihrem eigenen Keystore hinzufügen? [Nein]: \u0020 Trust.this.certificate.no.=Diesem Zertifikat vertrauen? [Nein]: \u0020 -New.prompt.=Neues {0}:\u0020 +New.prompt.={0} (neu):\u0020 Passwords.must.differ=Kennwörter müssen sich unterscheiden Re.enter.new.prompt.=Neues {0} erneut eingeben:\u0020 Re.enter.password.=Geben Sie das Kennwort erneut ein:\u0020 @@ -238,7 +238,7 @@ Is.name.correct.=Ist {0} richtig? no=Nein yes=Ja y=J -.defaultValue.=\u0020 [{0}]: \u0020 +.defaultValue.=\ [{0}]: \u0020 Alias.alias.has.no.key=Alias <{0}> verfügt über keinen Schlüssel Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key=Alias <{0}> verweist auf einen Eintragstyp, der kein Private-Key-Eintrag ist. Der Befehl -keyclone unterstützt nur das Klonen von Private-Key-Einträgen @@ -302,8 +302,8 @@ alias.in.keystore=Aussteller <%s> with.weak=%s (schwach) with.disabled=%s (deaktiviert) key.bit=%s-Schlüssel -key.bit.weak=%s Schlüssel (schwach) -key.bit.disabled=%s Schlüssel (deaktiviert) +key.bit.weak=%s-Schlüssel (schwach) +key.bit.disabled=%s-Schlüssel (deaktiviert) .PATTERN.printX509Cert.with.weak=Eigentümer: {0}\nAussteller: {1}\nSeriennummer: {2}\nGültig von: {3} bis: {4}\nZertifikatsfingerprints:\n\t SHA1: {5}\n\t SHA256: {6}\nSignaturalgorithmusname: {7}\nPublic-Key-Algorithmus von Subject: {8}\nVersion: {9} PKCS.10.with.weak=PKCS #10-Zertifikatsanforderung (Version 1.0)\nSubject: %1$s\nFormat: %2$s\nPublic Key: %3$s\nSignaturalgorithmus: %4$s\n verified.by.s.in.s.weak=Von %1$s in %2$s mit %3$s verifiziert @@ -312,7 +312,7 @@ whose.sigalg.usagesignedjar=%1$s verwendet den Signaturalgorithmus %2$s. Das gil Unable.to.parse.denyAfter.string.in.exception.message=denyAfter-Datumszeichenfolge in Ausnahmemeldung kann nicht geparst werden whose.sigalg.weak=%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko. whose.key.disabled=%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko und ist deaktiviert. -whose.key.weak=%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko. Wird in einem zukünftigen Update deaktiviert. +whose.key.weak=%1$s verwendet %2$s. Das gilt als Sicherheitsrisiko. Dieser Schlüssel wird in einem zukünftigen Update deaktiviert. jks.storetype.warning=Der %1$s-Keystore verwendet ein proprietäres Format. Es wird empfohlen, auf PKCS12 zu migrieren, das ein Industriestandardformat mit "keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12" ist. migrate.keystore.warning="%1$s" zu %4$s migriert. Der %2$s-Keystore wurde als "%3$s" gesichert. backup.keystore.warning=Der ursprüngliche Keystore "%1$s" wird als "%3$s" gesichert... diff --git a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties index 416cf51007f..63ba4f220dd 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties +++ b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties @@ -27,7 +27,7 @@ NEWLINE=\n STAR=******************************************* STARNN=*******************************************\n\n # keytool: Help part -.OPTION.=\u0020[OPTION]... +.OPTION.=\ [OPTION]... Options.=オプション: option.1.set.twice=%sオプションが複数回指定されています。最後のもの以外はすべて無視されます。 multiple.commands.1.2=1つのコマンドのみ許可されます: %1$sと%2$sの両方が指定されました。 @@ -178,9 +178,9 @@ Alias.alias.has.no.certificate=別名<{0}>には証明書がありません groupname.keysize.coexist=-groupnameと-keysizeの両方を指定できません deprecate.keysize.for.ec=-keysizeの指定によるECキーの生成は非推奨です。かわりに"-groupname %s"を使用してください。 Key.pair.not.generated.alias.alias.already.exists=キー・ペアは生成されませんでした。別名<{0}>はすでに存在します -size.bit.alg=%1$dビット%2$s -Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for={0}キー・ペアおよび自己署名証明書({1})を{2}日の有効性で生成しています\n\t対象: {3} -Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for={0}キー・ペアと<{2}>によって発行された証明書({1})を{3}日間の有効性で生成しています\n\t対象: {4} +size.bit.alg=%1$d-ビット %2$s +Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for={2}日間有効な{0}のキー・ペアと自己署名型証明書({1})を生成しています\n\tディレクトリ名: {3} +Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for={3}日間有効な{0}キー・ペアと<{2}>によって発行される証明書({1})を生成しています\n\tディレクトリ名: {4} Enter.key.password.for.alias.=<{0}>のキー・パスワードを入力してください .RETURN.if.same.as.keystore.password.=\t(キーストアのパスワードと同じ場合はRETURNを押してください): \u0020 Key.password.is.too.short.must.be.at.least.6.characters=キーのパスワードが短すぎます - 6文字以上を指定してください @@ -227,18 +227,18 @@ Enter.new.alias.name.RETURN.to.cancel.import.for.this.entry.=新しい別名を Enter.alias.name.=別名を入力してください: \u0020 .RETURN.if.same.as.for.otherAlias.=\t(<{0}>と同じ場合はRETURNを押してください) enter.dname.components=識別名を入力します。サブコンポーネントを空のままにする場合はドット(.)を1つ入力し、中カッコ内のデフォルト値を使用する場合は[ENTER]を押します。 -What.is.your.first.and.last.name.=姓名は何ですか。 -What.is.the.name.of.your.organizational.unit.=組織単位名は何ですか。 -What.is.the.name.of.your.organization.=組織名は何ですか。 -What.is.the.name.of.your.City.or.Locality.=都市名または地域名は何ですか。 -What.is.the.name.of.your.State.or.Province.=都道府県名または州名は何ですか。 -What.is.the.two.letter.country.code.for.this.unit.=この単位に該当する2文字の国コードは何ですか。 +What.is.your.first.and.last.name.=姓名を入力してください。 +What.is.the.name.of.your.organizational.unit.=組織単位名を入力してください。 +What.is.the.name.of.your.organization.=組織名を入力してください。 +What.is.the.name.of.your.City.or.Locality.=都市名または地域名を入力してください。 +What.is.the.name.of.your.State.or.Province.=都道府県名を入力してください。 +What.is.the.two.letter.country.code.for.this.unit.=この単位に該当する2文字の国コードを入力してください。 no.field.in.dname=少なくとも1つのフィールドを指定する必要があります。再度入力してください。 Is.name.correct.={0}でよろしいですか。 no=いいえ yes=はい y=y -.defaultValue.=\u0020 [{0}]: \u0020 +.defaultValue.=\ [{0}]: \u0020 Alias.alias.has.no.key=別名<{0}>にはキーがありません Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key=別名<{0}>が参照しているエントリ・タイプは秘密キー・エントリではありません。-keycloneコマンドは秘密キー・エントリのクローン作成のみをサポートします @@ -292,7 +292,7 @@ the.certificate=証明書 the.crl=CRL the.tsa.certificate=TSA証明書 the.input=入力 -reply=応答 +reply=返信 one.in.many=%1$s #%2$d / %3$d one.in.many1=%1$s #%2$d one.in.many2=署名者の%1$s #%2$d @@ -302,7 +302,7 @@ alias.in.keystore=発行者<%s> with.weak=%s (弱) with.disabled=%s (無効) key.bit=%sキー -key.bit.weak=%sキー(弱い) +key.bit.weak=%sキー(弱) key.bit.disabled=%sキー(無効) .PATTERN.printX509Cert.with.weak=所有者: {0}\n発行者: {1}\nシリアル番号: {2}\n有効期間の開始日: {3}終了日: {4}\n証明書のフィンガプリント:\n\t SHA1: {5}\n\t SHA256: {6}\n署名アルゴリズム名: {7}\nサブジェクト公開キー・アルゴリズム: {8}\nバージョン: {9} PKCS.10.with.weak=PKCS #10証明書リクエスト(バージョン1.0)\nサブジェクト: %1$s\nフォーマット: %2$s\n公開キー: %3$s\n署名アルゴリズム: %4$s\n @@ -312,7 +312,7 @@ whose.sigalg.usagesignedjar=%1$sは%2$s署名アルゴリズムを使用して Unable.to.parse.denyAfter.string.in.exception.message=例外メッセージのdenyAfter日付文字列を解析できません whose.sigalg.weak=%1$sは%2$s署名アルゴリズムを使用しており、これはセキュリティ・リスクとみなされます。 whose.key.disabled=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされ、無効化されています。 -whose.key.weak=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされます。今後の更新では無効になります。 +whose.key.weak=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされます。これは将来の更新で無効化されます。 jks.storetype.warning=%1$sキーストアは独自の形式を使用しています。"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12"を使用する業界標準の形式であるPKCS12に移行することをお薦めします。 migrate.keystore.warning="%1$s"が%4$sに移行されました。%2$sキーストアは"%3$s"としてバックアップされます。 backup.keystore.warning=元のキーストア"%1$s"は"%3$s"としてバックアップされます... diff --git a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties index 5aa27eb2ed4..1f96aa12c57 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties +++ b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties @@ -27,13 +27,13 @@ NEWLINE=\n STAR=******************************************* STARNN=*******************************************\n\n # keytool: Help part -.OPTION.=\u0020[OPTION]... -Options.=选项: +.OPTION.=\ [OPTION]... +Options.=选项: option.1.set.twice=多次指定了 %s 选项。除最后一个之外, 其余的将全部忽略。 multiple.commands.1.2=只允许一个命令: 同时指定了 %1$s 和 %2$s。 Use.keytool.help.for.all.available.commands=使用 "keytool -?, -h, or --help" 可输出此帮助消息 Key.and.Certificate.Management.Tool=密钥和证书管理工具 -Commands.=命令: +Commands.=命令: Use.keytool.command.name.help.for.usage.of.command.name=使用 "keytool -command_name --help" 可获取 command_name 的用法。\n使用 -conf 选项可指定预配置的选项文件。 # keytool: help: commands Generates.a.certificate.request=生成证书请求 @@ -114,7 +114,7 @@ verbose.output=详细输出 validity.number.of.days=有效天数 Serial.ID.of.cert.to.revoke=要撤销的证书的序列 ID # keytool: Running part -keytool.error.=keytool 错误:\u0020 +keytool.error.=keytool 错误:\u0020 Illegal.option.=非法选项: \u0020 Illegal.value.=非法值:\u0020 Unknown.password.type.=未知口令类型:\u0020 @@ -170,7 +170,7 @@ Certificate.reply.was.installed.in.keystore=证书回复已安装在密钥库中 Certificate.reply.was.not.installed.in.keystore=证书回复未安装在密钥库中 Certificate.was.added.to.keystore=证书已添加到密钥库中 Certificate.was.not.added.to.keystore=证书未添加到密钥库中 -.Storing.ksfname.=[正在存储{0}] +.Storing.ksfname.=[正在存储 {0}] alias.has.no.public.key.certificate.={0}没有公共密钥 (证书) Cannot.derive.signature.algorithm=无法派生签名算法 Alias.alias.does.not.exist=别名 <{0}> 不存在 @@ -179,8 +179,8 @@ groupname.keysize.coexist=无法同时指定 -groupname 和 -keysize deprecate.keysize.for.ec=为生成 EC 密钥指定 -keysize 已过时,请改为使用 "-groupname %s"。 Key.pair.not.generated.alias.alias.already.exists=未生成密钥对, 别名 <{0}> 已经存在 size.bit.alg=%1$d 位 %2$s -Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=正在为 {3} 生成有效期为 {2} 天的 {0} 密钥对和自签名证书 ({1})\n -Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=生成 {0} 密钥对和 <{2}> 颁发的证书 ({1}),有效期为 {3} 天 \n\t 对于:{4} +Generating.full.keyAlgName.key.pair.and.self.signed.certificate.sigAlgName.with.a.validity.of.days.for=正在为以下对象生成 {0} 密钥对和自签名证书 ({1})(有效期为 {2} 天):\n\t{3} +Generating.full.keyAlgName.key.pair.and.a.certificate.sigAlgName.issued.by.signerAlias.with.a.validity.of.days.for=正在为以下对象生成 {0} 密钥对和由 <{2}> 颁发的证书 ({1})(有效期为 {3} 天):\n\t{4} Enter.key.password.for.alias.=输入 <{0}> 的密钥口令 .RETURN.if.same.as.keystore.password.=\t(如果和密钥库口令相同, 按回车): \u0020 Key.password.is.too.short.must.be.at.least.6.characters=密钥口令太短 - 至少必须为 6 个字符 @@ -216,7 +216,7 @@ Do.you.still.want.to.add.it.no.=是否仍要添加? [否]: \u0020 Certificate.already.exists.in.system.wide.CA.keystore.under.alias.trustalias.=在别名 <{0}> 之下, 证书已经存在于系统范围的 CA 密钥库中 Do.you.still.want.to.add.it.to.your.own.keystore.no.=是否仍要将它添加到自己的密钥库? [否]: \u0020 Trust.this.certificate.no.=是否信任此证书? [否]: \u0020 -New.prompt.=新{0}:\u0020 +New.prompt.=新 {0}:\u0020 Passwords.must.differ=口令不能相同 Re.enter.new.prompt.=重新输入新{0}:\u0020 Re.enter.password.=再次输入口令:\u0020 @@ -238,14 +238,14 @@ Is.name.correct.={0}是否正确? no=否 yes=是 y=y -.defaultValue.=\u0020 [{0}]: \u0020 +.defaultValue.=\ [{0}]: \u0020 Alias.alias.has.no.key=别名 <{0}> 没有密钥 Alias.alias.references.an.entry.type.that.is.not.a.private.key.entry.The.keyclone.command.only.supports.cloning.of.private.key=别名 <{0}> 引用了不属于私有密钥条目的条目类型。-keyclone 命令仅支持对私有密钥条目的克隆 .WARNING.WARNING.WARNING.=***************** WARNING WARNING WARNING ***************** -Signer.d.=签名者 #%d: +Signer.d.=签名者 #%d: Certificate.d.=证书 #%d: -Timestamp.=时间戳: +Timestamp.=时间戳: Certificate.owner.=证书所有者:\u0020 Not.a.signed.jar.file=不是已签名的 jar 文件 No.certificate.from.the.SSL.server=没有来自 SSL 服务器的证书 @@ -256,7 +256,7 @@ No.certificate.from.the.SSL.server=没有来自 SSL 服务器的证书 Certificate.reply.does.not.contain.public.key.for.alias.=证书回复中不包含 <{0}> 的公共密钥 Incomplete.certificate.chain.in.reply=回复中的证书链不完整 Top.level.certificate.in.reply.=回复中的顶级证书:\n -.is.not.trusted.=... 是不可信的。 +.is.not.trusted.=... 是不可信的。\u0020 Install.reply.anyway.no.=是否仍要安装回复? [否]: \u0020 Public.keys.in.reply.and.keystore.don.t.match=回复中的公共密钥与密钥库不匹配 Certificate.reply.and.certificate.in.keystore.are.identical=证书回复与密钥库中的证书是相同的 @@ -269,14 +269,14 @@ Please.provide.keysize.for.secret.key.generation=请提供 -keysize 以生成密 warning.not.verified.make.sure.keystore.is.correct=警告: 未验证。请确保密钥库是正确的。 warning.not.verified.make.sure.keystore.is.correct.or.specify.trustcacerts=警告:未验证。请确保密钥库是正确的,或者指定 -trustcacerts。 -Extensions.=扩展:\u0020 +Extensions.=扩展:\u0020 .Empty.value.=(空值) Extension.Request.=扩展请求: Unknown.keyUsage.type.=未知 keyUsage 类型:\u0020 Unknown.extendedkeyUsage.type.=未知 extendedkeyUsage 类型:\u0020 Unknown.AccessDescription.type.=未知 AccessDescription 类型:\u0020 Unrecognized.GeneralName.type.=无法识别的 GeneralName 类型:\u0020 -This.extension.cannot.be.marked.as.critical.=无法将此扩展标记为“严重”。 +This.extension.cannot.be.marked.as.critical.=无法将此扩展标记为“严重”。\u0020 Odd.number.of.hex.digits.found.=找到奇数个十六进制数字:\u0020 Unknown.extension.type.=未知扩展类型:\u0020 command.{0}.is.ambiguous.=命令{0}不明确: @@ -299,11 +299,11 @@ one.in.many2=签名者 #%2$d 的 %1$s one.in.many3=签名者 #%3$d 的 %1$s #%2$d alias.in.cacerts=cacerts 中的发布者 <%s> alias.in.keystore=发布者 <%s> -with.weak=%s (弱) +with.weak=%s(弱) with.disabled=%s(禁用) key.bit=%s 密钥 key.bit.weak=%s 密钥(弱) -key.bit.disabled=%s 密钥(已禁用) +key.bit.disabled=%s 密钥(禁用) .PATTERN.printX509Cert.with.weak=所有者: {0}\n发布者: {1}\n序列号: {2}\n生效时间: {3}, 失效时间: {4}\n证书指纹:\n\t SHA1: {5}\n\t SHA256: {6}\n签名算法名称: {7}\n主体公共密钥算法: {8}\n版本: {9} PKCS.10.with.weak=PKCS #10 证书请求 (版本 1.0)\n主体: %1$s\n格式: %2$s\n公共密钥: %3$s\n签名算法: %4$s\n verified.by.s.in.s.weak=由 %2$s 中的 %1$s 以 %3$s 验证 @@ -312,7 +312,7 @@ whose.sigalg.usagesignedjar=%1$s 使用的 %2$s 签名算法被视为存在安 Unable.to.parse.denyAfter.string.in.exception.message=无法解析异常错误消息中的 denyAfter 日期字符串 whose.sigalg.weak=%1$s 使用的 %2$s 签名算法存在安全风险。 whose.key.disabled=%1$s 使用的 %2$s 被视为存在安全风险而且被禁用。 -whose.key.weak=%1$s 使用的 %2$s 被视为存在安全风险。在将来的更新中将禁用它。 +whose.key.weak=%1$s 使用的 %2$s 被视为存在安全风险。它将在未来的更新中被禁用。 jks.storetype.warning=%1$s 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。 migrate.keystore.warning=已将 "%1$s" 迁移到 %4$s。将 %2$s 密钥库作为 "%3$s" 进行了备份。 backup.keystore.warning=已将原始密钥库 "%1$s" 备份为 "%3$s"... diff --git a/src/java.base/share/classes/sun/security/util/resources/auth_zh_CN.properties b/src/java.base/share/classes/sun/security/util/resources/auth_zh_CN.properties index 6d677804544..663b3f8993f 100644 --- a/src/java.base/share/classes/sun/security/util/resources/auth_zh_CN.properties +++ b/src/java.base/share/classes/sun/security/util/resources/auth_zh_CN.properties @@ -24,22 +24,22 @@ # # NT principals -invalid.null.input.value=无效的空输入: {0} -NTDomainPrincipal.name=NTDomainPrincipal: {0} -NTNumericCredential.name=NTNumericCredential: {0} +invalid.null.input.value=无效的空输入:{0} +NTDomainPrincipal.name=NTDomainPrincipal:{0} +NTNumericCredential.name=NTNumericCredential:{0} Invalid.NTSid.value=无效的 NTSid 值 -NTSid.name=NTSid: {0} -NTSidDomainPrincipal.name=NTSidDomainPrincipal: {0} -NTSidGroupPrincipal.name=NTSidGroupPrincipal: {0} -NTSidPrimaryGroupPrincipal.name=NTSidPrimaryGroupPrincipal: {0} -NTSidUserPrincipal.name=NTSidUserPrincipal: {0} -NTUserPrincipal.name=NTUserPrincipal: {0} +NTSid.name=NTSid:{0} +NTSidDomainPrincipal.name=NTSidDomainPrincipal:{0} +NTSidGroupPrincipal.name=NTSidGroupPrincipal:{0} +NTSidPrimaryGroupPrincipal.name=NTSidPrimaryGroupPrincipal:{0} +NTSidUserPrincipal.name=NTSidUserPrincipal:{0} +NTUserPrincipal.name=NTUserPrincipal:{0} # UnixPrincipals -UnixNumericGroupPrincipal.Primary.Group.name=UnixNumericGroupPrincipal [主组]: {0} +UnixNumericGroupPrincipal.Primary.Group.name=UnixNumericGroupPrincipal [主组]:{0} UnixNumericGroupPrincipal.Supplementary.Group.name=UnixNumericGroupPrincipal [补充组]: {0} -UnixNumericUserPrincipal.name=UnixNumericUserPrincipal: {0} -UnixPrincipal.name=UnixPrincipal: {0} +UnixNumericUserPrincipal.name=UnixNumericUserPrincipal:{0} +UnixPrincipal.name=UnixPrincipal:{0} # com.sun.security.auth.login.ConfigFile Unable.to.properly.expand.config=无法正确扩展{0} @@ -53,8 +53,8 @@ Configuration.Error.Line.line.expected.expect.=配置错误: \n\t行 {0}: 应为 Configuration.Error.Line.line.system.property.value.expanded.to.empty.value=配置错误: \n\t行 {0}: 系统属性 [{1}] 扩展到空值 # com.sun.security.auth.module.JndiLoginModule -username.=用户名:\u0020 -password.=口令:\u0020 +username.=用户名:\u0020 +password.=密码:\u0020 # com.sun.security.auth.module.KeyStoreLoginModule Please.enter.keystore.information=请输入密钥库信息 @@ -63,5 +63,5 @@ Keystore.password.=密钥库口令:\u0020 Private.key.password.optional.=私有密钥口令 (可选):\u0020 # com.sun.security.auth.module.Krb5LoginModule -Kerberos.username.defUsername.=Kerberos 用户名 [{0}]:\u0020 -Kerberos.password.for.username.={0}的 Kerberos 口令:\u0020 +Kerberos.username.defUsername.=Kerberos 用户名 [{0}]:\u0020 +Kerberos.password.for.username.={0} 的 Kerberos 密码:\u0020 diff --git a/src/java.base/share/classes/sun/security/util/resources/security_ja.properties b/src/java.base/share/classes/sun/security/util/resources/security_ja.properties index b9ec0a82cb9..ff13b37cf3b 100644 --- a/src/java.base/share/classes/sun/security/util/resources/security_ja.properties +++ b/src/java.base/share/classes/sun/security/util/resources/security_ja.properties @@ -66,7 +66,7 @@ Login.Failure.all.modules.ignored=ログイン失敗: すべてのモジュー # sun.security.provider.PolicyParser duplicate.keystore.domain.name=重複するキーストア・ドメイン名: {0} duplicate.keystore.name=重複するキーストア名: {0} -number.=数\u0020 +number.=数値\u0020 expected.expect.read.end.of.file.=[{0}]ではなく[ファイルの終わり]が読み込まれました expected.read.end.of.file.=[;]ではなく[ファイルの終わり]が読み込まれました line.number.msg=行{0}: {1} diff --git a/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties b/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties index 0653fbdca52..6a4ec11de77 100644 --- a/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties +++ b/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties @@ -43,17 +43,17 @@ provided.null.OID.map=提供的 OID 映射为空值 NEWLINE=\n invalid.null.action.provided=提供了无效的空操作 invalid.null.Class.provided=提供了无效的空类 -Subject.=主体: \n -.Principal.=\t主用户:\u0020 -.Public.Credential.=\t公共身份证明:\u0020 -.Private.Credential.=\t专用身份证明:\u0020 +Subject.=主体:\n +.Principal.=\t主用户:\u0020 +.Public.Credential.=\t公共身份证明:\u0020 +.Private.Credential.=\t专用身份证明:\u0020 .Private.Credential.inaccessible.=\t无法访问专用身份证明\n Subject.is.read.only=主体为只读 attempting.to.add.an.object.which.is.not.an.instance.of.java.security.Principal.to.a.Subject.s.Principal.Set=正在尝试将一个非 java.security.Principal 实例的对象添加到主体的主用户集中 attempting.to.add.an.object.which.is.not.an.instance.of.class=正在尝试添加一个非{0}实例的对象 # javax.security.auth.login.AppConfigurationEntry -LoginModuleControlFlag.=LoginModuleControlFlag:\u0020 +LoginModuleControlFlag.=LoginModuleControlFlag:\u0020 # javax.security.auth.login.LoginContext Invalid.null.input.name=无效空输入: 名称 @@ -69,8 +69,8 @@ duplicate.keystore.name=密钥库名称重复: {0} number.=编号\u0020 expected.expect.read.end.of.file.=应为 [{0}], 读取的是 [文件结尾] expected.read.end.of.file.=应为 [;], 读取的是 [文件结尾] -line.number.msg=列{0}: {1} +line.number.msg=第 {0} 行:{1} line.number.expected.expect.found.actual.=行号 {0}: 应为 [{1}], 找到 [{2}] # sun.security.pkcs11.SunPKCS11 -PKCS11.Token.providerName.Password.=PKCS11 标记 [{0}] 口令:\u0020 +PKCS11.Token.providerName.Password.=PKCS11 标记 [{0}] 密码:\u0020 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties index 1144488773e..87ac233b6c7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties @@ -56,6 +56,7 @@ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: Content des Elements ''{0}'' ist nicht vollständig. ''{1}'' wird erwartet. cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: Übereinstimmungsplatzhalter ist streng, aber es kann keine Deklaration für Element ''{0}'' gefunden werden. cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: Ungültiger Content wurde beginnend mit Element ''{0}'' gefunden. An dieser Stelle wird kein untergeordnetes Element erwartet. + cvc-complex-type.2.4.d.1 = cvc-complex-type.2.4.d: Ungültiger Content wurde beginnend mit Element ''{0}'' gefunden. An dieser Stelle wird kein untergeordnetes Element ''{1}'' erwartet. cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: "{0}" darf maximal "{2}"-mal in der aktuellen Abfolge auftreten. Dieser Grenzwert wurde überschritten. An dieser Stelle wird eines von "{1}" erwartet. cvc-complex-type.2.4.f = cvc-complex-type.2.4.e: "{0}" darf maximal "{1}"-mal in der aktuellen Abfolge auftreten. Dieser Grenzwert wurde überschritten. An dieser Stelle wird kein untergeordnetes Element erwartet. cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: Ungültigen Inhalt gefunden, der mit Element "{0}" beginnt. "{1}" soll erwartungsgemäß mindestens "{2}"-mal in der aktuellen Abfolge auftreten. Eine weitere Instanz ist erforderlich, um diesen Constraint zu erfüllen. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties index 05e945bed9b..ad82476b1e8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties @@ -56,6 +56,7 @@ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: 要素''{0}''のコンテンツは不完全です。''{1}''のいずれかが必要です。 cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: ワイルドカードの一致は厳密ですが、要素''{0}''で宣言が見つかりません。 cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: 要素''{0}''で始まる無効なコンテンツが見つかりました。ここでは子要素を使用できません。 + cvc-complex-type.2.4.d.1 = cvc-complex-type.2.4.d: 要素''{0}''で始まる無効なコンテンツが見つかりました。ここでは子要素''{1}''を使用できません。 cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: ''{0}''は現在のシーケンスで最大''{2}''回発生することがあります。この制限を超えました。ここでは''{1}''のいずれかが必要です。 cvc-complex-type.2.4.f = cvc-complex-type.2.4.f: ''{0}''は現在のシーケンスで最大''{1}''回発生することがあります。この制限を超えました。ここでは子要素は使用できません。 cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: 要素''{0}''で始まる無効なコンテンツが見つかりました。''{1}''は現在のシーケンスで少なくとも''{2}''回発生する必要があります。この制約を満たすインスタンスがもう1つ必要です。 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties index f366acbb174..238cb63c869 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties @@ -56,6 +56,7 @@ cvc-complex-type.2.4.b = cvc-complex-type.2.4.b: 元素 ''{0}'' 的内容不完整。应为 ''{1}'' 之一。 cvc-complex-type.2.4.c = cvc-complex-type.2.4.c: 通配符的匹配很全面, 但无法找到元素 ''{0}'' 的声明。 cvc-complex-type.2.4.d = cvc-complex-type.2.4.d: 发现了以元素 ''{0}'' 开头的无效内容。此处不应含有子元素。 + cvc-complex-type.2.4.d.1 = cvc-complex-type.2.4.d: 发现了以元素 ''{0}'' 开头的无效内容。此处不应含有子元素 ''{1}''。 cvc-complex-type.2.4.e = cvc-complex-type.2.4.e: ''{0}'' 在当前序列中最多可以出现 ''{2}'' 次。已超过此限制。此处预期为 ''{1}'' 之一。 cvc-complex-type.2.4.f = cvc-complex-type.2.4.f: ''{0}'' 在当前序列中最多可以出现 ''{1}'' 次。已超过此限制。此处预期没有子元素。 cvc-complex-type.2.4.g = cvc-complex-type.2.4.g: 发现了以元素 ''{0}'' 开头的无效内容。''{1}'' 预期在当前序列中最少出现 ''{2}'' 次。另外一个实例必须满足此约束条件。 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java index 272dca058d3..eacc96e70fb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,7 +31,7 @@ * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced - * @LastModified: Nov 2024 + * @LastModified: Apr 2025 */ public class XPATHErrorResources_de extends ListResourceBundle { @@ -305,7 +305,6 @@ public class XPATHErrorResources_de extends ListResourceBundle public static final String ER_XPATH_ERROR = "ER_XPATH_ERROR"; //BEGIN: Keys needed for exception messages of JAXP 1.3 XPath API implementation - public static final String ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED = "ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED"; public static final String ER_RESOLVE_VARIABLE_RETURNS_NULL = "ER_RESOLVE_VARIABLE_RETURNS_NULL"; public static final String ER_NO_XPATH_VARIABLE_RESOLVER = "ER_NO_XPATH_VARIABLE_RESOLVER"; public static final String ER_NO_XPATH_FUNCTION_PROVIDER = "ER_NO_XPATH_FUNCTION_PROVIDER"; @@ -766,11 +765,6 @@ public class XPATHErrorResources_de extends ListResourceBundle //BEGIN: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation - /** Field ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED */ - - { ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED, - "Erweiterungsfunktion \"{0}\" kann nicht aufgerufen werden, wenn das Feature \"XMLConstants.FEATURE_SECURE_PROCESSING\" auf \"true\" gesetzt ist."}, - /** Field ER_RESOLVE_VARIABLE_RETURNS_NULL */ { ER_RESOLVE_VARIABLE_RETURNS_NULL, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java index 1b707cd7820..8d8d5828da1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,7 +31,7 @@ * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced - * @LastModified: Nov 2024 + * @LastModified: Apr 2025 */ public class XPATHErrorResources_ja extends ListResourceBundle { @@ -305,7 +305,6 @@ public class XPATHErrorResources_ja extends ListResourceBundle public static final String ER_XPATH_ERROR = "ER_XPATH_ERROR"; //BEGIN: Keys needed for exception messages of JAXP 1.3 XPath API implementation - public static final String ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED = "ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED"; public static final String ER_RESOLVE_VARIABLE_RETURNS_NULL = "ER_RESOLVE_VARIABLE_RETURNS_NULL"; public static final String ER_NO_XPATH_VARIABLE_RESOLVER = "ER_NO_XPATH_VARIABLE_RESOLVER"; public static final String ER_NO_XPATH_FUNCTION_PROVIDER = "ER_NO_XPATH_FUNCTION_PROVIDER"; @@ -766,11 +765,6 @@ public class XPATHErrorResources_ja extends ListResourceBundle //BEGIN: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation - /** Field ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED */ - - { ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED, - "\u62E1\u5F35\u95A2\u6570: XMLConstants.FEATURE_SECURE_PROCESSING\u6A5F\u80FD\u304Ctrue\u306B\u8A2D\u5B9A\u3055\u308C\u308B\u3068''{0}''\u3092\u8D77\u52D5\u3067\u304D\u307E\u305B\u3093\u3002"}, - /** Field ER_RESOLVE_VARIABLE_RETURNS_NULL */ { ER_RESOLVE_VARIABLE_RETURNS_NULL, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java index dd9e507a8f0..3e1969357fb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,7 +31,7 @@ * Also you need to update the count of messages(MAX_CODE)or * the count of warnings(MAX_WARNING) [ Information purpose only] * @xsl.usage advanced - * @LastModified: Nov 2024 + * @LastModified: Apr 2025 */ public class XPATHErrorResources_zh_CN extends ListResourceBundle { @@ -305,7 +305,6 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle public static final String ER_XPATH_ERROR = "ER_XPATH_ERROR"; //BEGIN: Keys needed for exception messages of JAXP 1.3 XPath API implementation - public static final String ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED = "ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED"; public static final String ER_RESOLVE_VARIABLE_RETURNS_NULL = "ER_RESOLVE_VARIABLE_RETURNS_NULL"; public static final String ER_NO_XPATH_VARIABLE_RESOLVER = "ER_NO_XPATH_VARIABLE_RESOLVER"; public static final String ER_NO_XPATH_FUNCTION_PROVIDER = "ER_NO_XPATH_FUNCTION_PROVIDER"; @@ -766,11 +765,6 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle //BEGIN: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation - /** Field ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED */ - - { ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED, - "\u5F53 XMLConstants.FEATURE_SECURE_PROCESSING \u529F\u80FD\u8BBE\u7F6E\u4E3A\u201C\u771F\u201D\u65F6, \u4E0D\u80FD\u8C03\u7528\u6269\u5C55\u51FD\u6570 ''{0}''\u3002"}, - /** Field ER_RESOLVE_VARIABLE_RETURNS_NULL */ { ER_RESOLVE_VARIABLE_RETURNS_NULL, diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties index 8761d334157..538b5a6c03b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -251,7 +251,7 @@ compiler.misc.no.suitable.functional.intf.inst=Funktionsschnittstellendeskriptor compiler.misc.bad.intersection.target.for.functional.expr=Ungültiges Schnittmengentypziel für Lambda oder Methodenreferenz\n{0} # 0: symbol or type -compiler.misc.not.an.intf.component=Komponententyp {0} ist keine Schnittstelle +compiler.misc.not.an.intf.component=Komponententyp {0} ist keine Schnittstelle oder kein java.lang.Object # 0: kind name, 1: message segment compiler.err.invalid.mref=Ungültige {0}-Referenz\n{1} @@ -389,9 +389,9 @@ compiler.err.duplicate.class=Doppelte Klasse: {0} # 0: string compiler.err.bad.file.name=Ungültiger Dateiname: {0} -compiler.err.implicit.class.should.not.have.package.declaration=Implizit deklarierte Klasse darf keine Packagedeklaration aufweisen +compiler.err.implicit.class.should.not.have.package.declaration=Kompakte Quelldatei darf keine Packagedeklaration aufweisen -compiler.err.implicit.class.does.not.have.main.method=Implizit deklarierte Klasse weist keine Hauptmethode im Format "void main()" oder "void main(String[] args)" auf +compiler.err.implicit.class.does.not.have.main.method=Kompakte Quelldatei weist keine Hauptmethode im Format "void main()" oder "void main(String[] args)" auf # 0: name, 1: name compiler.err.same.binary.name=Klassen {0} und {1} haben denselben binären Namen @@ -501,6 +501,8 @@ compiler.err.illegal.combination.of.modifiers=Unzulässige Kombination aus Modif compiler.err.illegal.enum.static.ref=Unzulässige Referenz zu statischem Feld aus Initializer +compiler.err.illegal.char.literal.multiple.surrogates=Zeichenliteral enthält mehrere UTF-16-Codeeinheiten + compiler.err.illegal.esc.char=Unzulässiges Escapezeichen compiler.err.illegal.forward.ref=Unzulässige Vorwärtsreferenz @@ -511,8 +513,10 @@ compiler.err.not.in.profile={0} ist in Profil "{1}" nicht verfügbar # 0: symbol compiler.warn.forward.ref=Referenz zu Variable "{0}", bevor sie initialisiert wurde +# lint: this-escape compiler.warn.possible.this.escape=Mögliches "this"-Escape vor vollständiger Initialisierung der Unterklasse +# lint: this-escape compiler.warn.possible.this.escape.location=Vorheriges mögliches "This"-Escape erfolgt hier per Aufruf compiler.err.illegal.self.ref=Selbstreferenz in Initializer @@ -527,8 +531,10 @@ compiler.err.illegal.line.end.in.char.lit=Unzulässiges Zeilenende in Zeichenlit compiler.err.illegal.text.block.open=Unzulässige Sequenz für Öffnungstrennzeichen von Textblock. Zeilenabschlusszeichen fehlt +# lint: text-blocks compiler.warn.inconsistent.white.space.indentation=Inkonsistenter Leerzeicheneinzug +# lint: text-blocks compiler.warn.trailing.white.space.will.be.removed=Nachgestelltes Leerzeichen wird entfernt compiler.err.illegal.nonascii.digit=Unzulässige Nicht-ASCII-Ziffer @@ -1112,6 +1118,7 @@ compiler.err.cant.read.file=Lesen nicht möglich: {0} compiler.err.plugin.not.found=Plug-in nicht gefunden: {0} # 0: path +# lint: path compiler.warn.locn.unknown.file.on.module.path=Unbekannte Datei in Modulpfad: {0} @@ -1131,6 +1138,7 @@ compiler.err.locn.cant.get.module.name.for.jar=Modulname für {0} kann nicht bes compiler.err.multi-module.outdir.cannot.be.exploded.module=Im Modus für mehrere Module kann das Ausgabeverzeichnis kein entpacktes Modul sein: {0} # 0: path +# lint: path compiler.warn.outdir.is.in.exploded.module=Das Ausgabeverzeichnis befindet sich in einem entpackten Modul: {0} # 0: file object @@ -1182,6 +1190,7 @@ compiler.misc.x.print.rounds=Runde {0}:\n\tEingabedateien: {1}\n\tAnnotationen: compiler.warn.file.from.future=Änderungsdatum liegt in der Zukunft für Datei {0} # 0: path +# lint: output-file-clash compiler.warn.output.file.clash=Ausgabedatei mehrmals geschrieben: {0} ##### @@ -1335,51 +1344,67 @@ compiler.warn.warning=Warnung:\u0020 compiler.warn.lintOption=[{0}]\u0020 # 0: symbol +# lint: serial compiler.warn.constant.SVUID=serialVersionUID muss Konstante in Klasse {0} sein +# lint: dangling-doc-comments compiler.warn.dangling.doc.comment=Dokumentationskommentar ist an keine Deklaration angehängt # 0: path +# lint: path compiler.warn.dir.path.element.not.found=Ungültiges Pfadelement "{0}": Verzeichnis nicht vorhanden # 0: file name +# lint: path compiler.warn.dir.path.element.not.directory=Ungültiges Pfadelement "{0}": kein Verzeichnis # 0: symbol, 1: symbol, 2: symbol +# lint: missing-explicit-ctor compiler.warn.missing-explicit-ctor=Klasse {0} in exportiertem Package {1} deklariert keine expliziten Konstruktoren und stellt daher einen Standardkonstruktor für Clients des Moduls {2} bereit +# lint: strictfp compiler.warn.strictfp=Ab Release 17 werden alle Gleitkommaausdrücke streng ausgewertet. Daher ist "strictfp" nicht erforderlich +# lint: finally compiler.warn.finally.cannot.complete=Finally-Klausel kann nicht normal abgeschlossen werden # 0: name +# lint: module compiler.warn.poor.choice.for.module.name=Modulnamenskomponente {0} darf keine Ziffern am Ende enthalten # 0: string +# lint: incubating compiler.warn.incubating.modules=Inkubatormodul(e) verwendet: {0} # 0: symbol, 1: symbol +# lint: deprecation compiler.warn.has.been.deprecated={0} in {1} ist veraltet # 0: symbol, 1: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal={0} in {1} ist veraltet und wurde zum Entfernen markiert # 0: symbol +# lint: preview compiler.warn.is.preview={0} ist eine Vorschau-API, die in einem zukünftigen Release entfernt werden kann. # 0: symbol compiler.err.is.preview={0} ist eine Vorschau-API, die standardmäßig deaktiviert ist.\n(Verwenden Sie --enable-preview, um Vorschau-APIs zu aktivieren) # 0: symbol +# lint: preview compiler.warn.is.preview.reflective={0} ist eine reflektive Vorschau-API, die in einem zukünftigen Release entfernt werden kann. # 0: symbol, 1: symbol +# lint: restricted compiler.warn.restricted.method={0}.{1} ist eine eingeschränkte Methode.\n(Eingeschränkte Methoden sind nicht sicher und können bei falscher Verwendung die JRE zum Absturz bringen oder den Arbeitsspeicher beschädigen) # 0: symbol +# lint: deprecation compiler.warn.has.been.deprecated.module=Modul {0} ist veraltet # 0: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal.module=Modul {0} ist veraltet und wurde zum Entfernen markiert # 0: symbol @@ -1388,10 +1413,13 @@ compiler.warn.sun.proprietary={0} ist eine interne proprietäre API, die in eine compiler.warn.illegal.char.for.encoding=Nicht zuordenbares Zeichen für Codierung {0} # 0: symbol +# lint: serial compiler.warn.improper.SVUID=serialVersionUID muss als "static final" in Klasse {0} deklariert sein +# lint: serial compiler.warn.improper.SPF=serialPersistentFields muss als "private static final" deklariert sein, um in Kraft zu treten +# lint: serial compiler.warn.SPF.null.init=serialPersistentFields tritt bei Initialisierung als Null nicht in Kraft.\nFühren Sie die Initialisierung zu einem leeren Array aus, um keine Felder anzugeben @@ -1405,82 +1433,111 @@ compiler.warn.unreachable.catch=Nicht erreichbare Catch-Klausel\nAusgelöster Ty compiler.warn.unreachable.catch.1=Nicht erreichbare Catch-Klausel\nAusgelöste Typen {0} wurden bereits abgefangen # 0: symbol +# lint: serial compiler.warn.long.SVUID=serialVersionUID muss den Typ "long" in Klasse {0} aufweisen +# lint: serial compiler.warn.OSF.array.SPF=serialPersistentFields muss den Typ "java.io.ObjectStreamField[]" aufweisen, um in Kraft zu treten # 0: symbol +# lint: serial compiler.warn.missing.SVUID=Serialisierbare Klasse {0} enthält keine Definition von serialVersionUID # 0: name +# lint: serial compiler.warn.serializable.missing.access.no.arg.ctor=Zugriff auf einen no-arg-Konstruktor in der ersten nicht serialisierbaren Superklasse {0} nicht möglich # 0: name +# lint: serial compiler.warn.serial.method.not.private=Serialisierungsbezogene Methode {0} nicht als privat deklariert # 0: name +# lint: serial compiler.warn.serial.concrete.instance.method=Serialisierungsbezogene Methode {0} muss eine konkrete Instanzmethode sein, um in Kraft zu treten. Sie darf nicht abstrakt oder statisch sein # 0: name +# lint: serial compiler.warn.serial.method.static=Serialisierungsbezogene Methode {0} ist als statisch deklariert. Sie muss stattdessen eine Instanzmethode sein, um in Kraft zu treten. # 0: name +# lint: serial compiler.warn.serial.method.no.args=Serialisierungsbezogene Methode {0} darf keine Parameter aufweisen, um in Kraft zu treten # 0: name, 1: number +# lint: serial compiler.warn.serial.method.one.arg=Serialisierungsbezogene Methode {0} muss genau einen Parameter aufweisen, um in Kraft zu treten. Sie darf nicht {1} Parameter enthalten # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.parameter.type=Der einzige Parameter der serialisierungsbezogenen Methode {0} muss den Typ {1} haben, um in Kraft zu treten. Er darf nicht den Typ {2} aufweisen # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.unexpected.return.type=Serialisierungsbezogene Methode {0} wurde mit dem Rückgabetyp {1} und nicht dem erwarteten Typ {2} deklariert.\nMit dieser Deklaration ist die Methode ungültig für die Serialisierung # 0: name, 1: type +# lint: serial compiler.warn.serial.method.unexpected.exception=Serialisierungsbezogene Methode {0} wurde zum Auslösen eines unerwarteten Typs {1} deklariert +# lint: serial compiler.warn.ineffectual.serial.field.interface=serialPersistentFields ist in einer Schnittstelle nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.serial.field.enum=Serialisierungsbezogenes Feld {0} ist in einer Enum-Klasse nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.enum=Serialisierungsbezogene Methode {0} ist in einer Enum-Klasse nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.extern.method.enum=Externalisierungsbezogene Methode {0} ist in einer Enum-Klasse nicht effektiv +# lint: serial compiler.warn.ineffectual.serial.field.record=serialPersistentFields ist in einer Datensatzklasse nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.record=Serialisierungsbezogene Methode {0} ist in einer Datensatzklasse nicht effektiv # 0: string +# lint: serial compiler.warn.ineffectual.externalizable.method.record=Externalisierungsbezogene Methode {0} ist in einer Datensatzklasse nicht effektiv # 0: name +# lint: serial compiler.warn.ineffectual.serial.method.externalizable=Serialisierungsbezogene Methode {0} ist in einer externalisierbaren Klasse nicht effektiv +# lint: serial compiler.warn.ineffectual.serial.field.externalizable=serialPersistentFields ist in einer externalisierbaren Klasse nicht effektiv +# lint: serial compiler.warn.externalizable.missing.public.no.arg.ctor=Eine externalisierbare Klasse erfordert einen öffentlichen no-arg-Konstruktor +# lint: serial compiler.warn.non.serializable.instance.field=Nicht transientes Instanzfeld einer serialisierbaren Klasse mit einem nicht serialisierbaren Typ deklariert # 0: type +# lint: serial compiler.warn.non.serializable.instance.field.array=Nicht transientes Instanzfeld einer serialisierbaren Klasse wurde mit einem Array mit einem nicht serialisierbaren Basiskomponententyp {0} deklariert +# lint: serial compiler.warn.non.private.method.weaker.access=Serialisierungsbezogene Methode, die in einer Schnittstelle als nicht privat deklariert ist, verhindert,\ndass Klassen, die die Schnittstelle implementieren, die Methode als privat deklarieren +# lint: serial compiler.warn.default.ineffective=Serialisierungsbezogene Standardmethode aus einer Schnittstelle wird nicht von der Serialisierung für eine implementierende Klasse ausgeführt # 0: symbol, 1: symbol, 2: symbol, 3: symbol +# lint: overloads compiler.warn.potentially.ambiguous.overload={0} in {1} ist möglicherweise mehrdeutig mit {2} in {3} # 0: message segment +# lint: overrides compiler.warn.override.varargs.missing={0}. Außer Kraft gesetzte Methode umfasst kein "..." # 0: message segment +# lint: overrides compiler.warn.override.varargs.extra={0}. In außer Kraft setzender Methode fehlt "..." # 0: message segment @@ -1490,11 +1547,14 @@ compiler.warn.override.bridge={0}. Außer Kraft setzende Methode ist eine Bridge compiler.warn.pkg-info.already.seen=Die Datei package-info.java wurde bereits für Package {0} gefunden # 0: path +# lint: path compiler.warn.path.element.not.found=Ungültiges Pfadelement "{0}": Datei oder Verzeichnis nicht vorhanden +# lint: fallthrough compiler.warn.possible.fall-through.into.case=Möglicher Fallthrough in Case # 0: type +# lint: cast compiler.warn.redundant.cast=Redundantes Casting in {0} # 0: number @@ -1507,15 +1567,19 @@ compiler.warn.big.major.version={0}: Hauptversion {1} ist neuer als {2}, die hö compiler.warn.invalid.utf8.in.classfile={0}: Klassendatei enthält ungültige UTF-8-Codierung: {1} # 0: kind name, 1: symbol +# lint: static compiler.warn.static.not.qualified.by.type=Statische {0} muss mit Typname {1} anstelle eines Ausdrucks qualifiziert werden # 0: kind name +# lint: static compiler.warn.static.not.qualified.by.type2={0} (statisch) darf nicht als Member einer anonymen Klasse verwendet werden # 0: string, 1: fragment +# lint: options compiler.warn.source.no.bootclasspath=Bootstrap Classpath ist nicht zusammen mit -source {0} festgelegt\n{1} # 0: string, 1: fragment +# lint: options compiler.warn.source.no.system.modules.path=Systemmodulpfad ist nicht zusammen mit -source {0} festgelegt\n{1} # 0: string @@ -1531,9 +1595,11 @@ compiler.misc.source.no.bootclasspath.with.target=Wenn Sie den Bootstrap Classpa compiler.misc.source.no.system.modules.path.with.target=Wenn Sie den Speicherort der Systemmodule nicht festlegen, kann dies zu Klassendateien führen, die auf JDK {0} nicht ausgeführt werden können\n--release {0} wird anstelle von -source {0} -target {1} empfohlen, weil dadurch der Speicherort der Systemmodule automatisch festgelegt wird # 0: string +# lint: options compiler.warn.option.obsolete.source=Quellwert {0} ist veraltet und wird in einem zukünftigen Release entfernt # 0: target +# lint: options compiler.warn.option.obsolete.target=Zielwert {0} ist veraltet und wird in einem zukünftigen Release entfernt # 0: string, 1: string @@ -1542,13 +1608,17 @@ compiler.err.option.removed.source=Quelloption {0} wird nicht mehr unterstützt. # 0: target, 1: target compiler.err.option.removed.target=Zieloption {0} wird nicht mehr unterstützt. Verwenden Sie {1} oder höher. +# lint: options compiler.warn.option.obsolete.suppression=Verwenden Sie -Xlint:-options, um Warnungen zu veralteten Optionen zu unterdrücken. # 0: name, 1: number, 2: number, 3: number, 4: number +# lint: classfile compiler.warn.future.attr={0}-Attribut, das in Klassendateien der Version {1}.{2} eingeführt wurde, wird in Klassendateien der Version {3}.{4} ignoriert +# lint: requires-automatic compiler.warn.requires.automatic=Erfordert Direktive für ein automatisches Modul +# lint: requires-transitive-automatic compiler.warn.requires.transitive.automatic=Erfordert transitive-Direktive für ein automatisches Modul # Warnings related to annotation processing @@ -1556,40 +1626,50 @@ compiler.warn.requires.transitive.automatic=Erfordert transitive-Direktive für compiler.warn.proc.package.does.not.exist=Package {0} ist nicht vorhanden # 0: string +# lint: processing compiler.warn.proc.file.reopening=Versuch, mehrmals eine Datei für "{0}" zu erstellen # 0: string +# lint: processing compiler.warn.proc.type.already.exists=Es ist bereits eine Datei für Typ "{0}" im Quellpfad oder Classpath vorhanden # 0: string +# lint: processing compiler.warn.proc.type.recreate=Versuch, mehrmals eine Datei für Typ "{0}" zu erstellen # 0: string +# lint: processing compiler.warn.proc.illegal.file.name=Datei kann nicht für unzulässigen Namen "{0}" erstellt werden. # 0: string, 1: string +# lint: processing compiler.warn.proc.suspicious.class.name=Datei für einen Typ, dessen Name mit {1} endet, wird erstellt: "{0}" # 0: string compiler.warn.proc.file.create.last.round=Datei für Typ "{0}", die in der letzten Runde erstellt wurde, wird keiner Annotationsverarbeitung unterzogen. # 0: string, 1: string +# lint: processing compiler.warn.proc.malformed.supported.string=Nicht wohlgeformte Zeichenfolge "{0}" für eine unterstützte Annotationsschnittstelle von Prozessor "{1}" zurückgegeben # 0: set of string +# lint: processing compiler.warn.proc.annotations.without.processors=Diese Annotationen wurden von keinem Prozessor beansprucht: {0} # 0: source version, 1: string, 2: string compiler.warn.proc.processor.incompatible.source.version=Unterstützte Quellversion "{0}" von Annotationsprozessor "{1}" kleiner als -source "{2}" # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.option.name=Doppelte unterstützte Option "{0}" von Annotationsprozessor "{1}" zurückgegeben # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.supported.annotation=Doppelte unterstützte Annotationsschnittstelle "{0}" von Annotationsprozessor "{1}" zurückgegeben # 0: string +# lint: processing compiler.warn.proc.redundant.types.with.wildcard=Annotationsprozessor "{0}" unterstützt redundant sowohl "*" als auch andere Annotationsschnittstellen compiler.warn.proc.proc-only.requested.no.procs=Annotationsverarbeitung ohne Kompilierung angefordert, aber keine Prozessoren gefunden. @@ -1608,42 +1688,56 @@ compiler.warn.proc.unclosed.type.files=Nicht geschlossene Dateien für die Typen # 0: string compiler.warn.proc.unmatched.processor.options=Die folgenden Optionen wurden von keinem Prozessor erkannt: "{0}" +# lint: try compiler.warn.try.explicit.close.call=Expliziter Aufruf von close() für eine automatisch schließbare Ressource # 0: symbol +# lint: try compiler.warn.try.resource.not.referenced=Automatisch schließbare Ressource {0} wird nie im Body der entsprechenden try-Anweisung referenziert # 0: type +# lint: try compiler.warn.try.resource.throws.interrupted.exc=Automatisch schließbare Ressource {0} umfasst die Mitgliedsmethode close(), die InterruptedException auslösen könnte +# lint: unchecked compiler.warn.unchecked.assign=Nicht geprüfte Zuweisung: {0} zu {1} # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.assign.to.var=Nicht geprüfte Zuweisung zu Variable {0} als Mitglied des Raw-Typs {1} # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.call.mbr.of.raw.type=Nicht geprüfter Aufruf von {0} als Mitglied des Raw-Typs {1} +# lint: unchecked compiler.warn.unchecked.cast.to.type=Nicht geprüftes Casting zu Typ {0} # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol +# lint: unchecked compiler.warn.unchecked.meth.invocation.applied=Nicht geprüfter Methodenaufruf: {0} {1} in {4} {5} wird auf die angegebenen Typen angewendet\nErforderlich: {2}\nErmittelt: {3} # 0: type +# lint: unchecked compiler.warn.unchecked.generic.array.creation=Nicht geprüfte Erstellung eines generischen Arrays für varargs-Parameter des Typs {0} # 0: type +# lint: unchecked compiler.warn.unchecked.varargs.non.reifiable.type=Möglich Heap-Beschädigung aus parametrisiertem vararg-Typ {0} # 0: symbol +# lint: varargs compiler.warn.varargs.unsafe.use.varargs.param=Varargs-Methode könnte Heap-Beschädigung aus nicht reifizierbarem varargs-Parameter {0} verursachen +# lint: dep-ann compiler.warn.missing.deprecated.annotation=Veraltetes Element ist nicht mit @Deprecated-Annotation versehen # 0: kind name +# lint: deprecation compiler.warn.deprecated.annotation.has.no.effect=@Deprecated-Annotation hat keine Auswirkung auf diese {0}-Deklaration # 0: string +# lint: path compiler.warn.invalid.path=Ungültiger Dateiname: {0} compiler.warn.doclint.not.available=Kein Serviceprovider für doclint verfügbar @@ -1653,22 +1747,28 @@ compiler.err.invalid.path=Ungültiger Dateiname: {0} # 0: path +# lint: path compiler.warn.invalid.archive.file=Unerwartete Datei in Pfad: {0} # 0: path +# lint: path compiler.warn.unexpected.archive.file=Unerwartete Erweiterung für Archivdatei: {0} # 0: path compiler.err.no.zipfs.for.archive=Kein Dateisystemprovider zur Verarbeitung dieser Datei verfügbar: {0} +# lint: divzero compiler.warn.div.zero=Division durch Null +# lint: empty compiler.warn.empty.if=Leere Anweisung nach "if" # 0: type, 1: name +# lint: classfile compiler.warn.annotation.method.not.found=Annotationsmethode "{1}()" kann nicht in Typ "{0}" gefunden werden # 0: type, 1: name, 2: message segment +# lint: classfile compiler.warn.annotation.method.not.found.reason=Annotationsmethode "{1}()" kann nicht in Typ "{0}" gefunden werden: {2} # 0: list of annotation, 1: symbol, 2: name, 3: message segment @@ -1681,6 +1781,7 @@ compiler.warn.unknown.enum.constant=Unbekannte Enum-Konstante {1}.{2} compiler.warn.unknown.enum.constant.reason=Unbekannte Enum-Konstante {1}.{2}\nGrund: {3} # 0: type, 1: type +# lint: rawtypes compiler.warn.raw.class.use=Raw-Typ gefunden: {0}\nTypargumente für generische Klasse {1} fehlen compiler.warn.diamond.redundant.args=Redundante Typargumente in neuem Ausdruck (verwenden Sie stattdessen den Rautenoperator). @@ -1692,12 +1793,15 @@ compiler.warn.potential.lambda.found=Die Erstellung dieser anonymen inneren Klas compiler.warn.method.redundant.typeargs=Redundante Typargumente in Methodenaufruf. # 0: symbol, 1: message segment +# lint: varargs compiler.warn.varargs.redundant.trustme.anno=Redundante {0}-Annotation. {1} # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.element=Zugriff auf Mitglied {0} aus serialisierbarem Element kann öffentlich für nicht vertrauenswürdigen Code zugänglich sein # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.lambda=Zugriff auf Mitglied {0} aus serialisierbarem Lambda kann öffentlich für nicht vertrauenswürdigen Code zugänglich sein ##### @@ -1810,9 +1914,11 @@ compiler.misc.bad.enclosing.class=Ungültige einschließende Klasse für {0}: {1 compiler.misc.bad.enclosing.method=Ungültiges einschließendes Methodenattribut für Klasse {0} # 0: file name +# lint: classfile compiler.warn.runtime.visible.invisible.param.annotations.mismatch=Die Längen der Parameter im RuntimeVisibleParameterAnnotations-Attribut und RuntimeInvisibleParameterAnnotations-Attribut in {0} stimmen nicht überein. Beide Attribute werden ignoriert # 0: file name +# lint: classfile compiler.warn.runtime.invisible.parameter.annotations=Die Attribute RuntimeVisibleParameterAnnotations und RuntimeInvisibleParameterAnnotations in {0} können nicht den Parametern der Methode zugeordnet werden compiler.misc.bad.const.pool.tag=Ungültiges Konstantenpooltag: {0} @@ -1904,6 +2010,7 @@ compiler.err.prob.found.req=Inkompatible Typen: {0} compiler.misc.prob.found.req=Inkompatible Typen: {0} # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.prob.found.req={0}\nErforderlich: {2}\nErmittelt: {1} # 0: type, 1: type @@ -1913,6 +2020,7 @@ compiler.misc.inconvertible.types={0} kann nicht in {1} konvertiert werden compiler.misc.possible.loss.of.precision=Möglicher Verlust bei Konvertierung von {0} in {1} # 0: type, 1: type +# lint: lossy-conversions compiler.warn.possible.loss.of.precision=Möglicher Verlust eines impliziten Cast von {0} bis {1} in zusammengesetzter Zuweisung compiler.misc.unchecked.assign=Nicht geprüfte Konvertierung @@ -2035,6 +2143,7 @@ compiler.misc.varargs.argument.mismatch=Keine übereinstimmenden varargs; {0} ##### # 0: symbol or type, 1: file name +# lint: auxiliaryclass compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file=Auf Auxiliary-Klasse {0} in {1} darf nicht von außerhalb der eigenen Quelldatei zugegriffen werden ## The first argument ({0}) is a "kindname". @@ -2174,12 +2283,15 @@ compiler.err.override.weaker.access={0}\nVersuch, niedrigere Zugriffsberechtigun compiler.err.override.incompatible.ret={0}\nRückgabetyp {1} ist nicht mit {2} kompatibel # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.override.unchecked.ret={0}\nRückgabetyp erfordert eine nicht geprüfte Konvertierung von {1} in {2} # 0: message segment, 1: type +# lint: unchecked compiler.warn.override.unchecked.thrown={0}\nAußer Kraft gesetzte Methode löst nicht {1} aus # 0: symbol +# lint: overrides compiler.warn.override.equals.but.not.hashcode=Klasse {0} setzt Gleichwertige außer Kraft. hashCode-Methode wird aber weder von der Klasse noch einer Superklasse außer Kraft gesetzt ## The following are all possible strings for the first argument ({0}) of the @@ -2245,12 +2357,15 @@ compiler.err.preview.feature.disabled.plural={0} sind ein Vorschaufeature, das s compiler.err.preview.feature.disabled.classfile=Klassendatei für {0} verwendet Vorschaufeatures von Java SE {1}.\n(Verwenden Sie --enable-preview, um das Laden von Klassendateien mit Vorschaufeatures zu ermöglichen) # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use={0} ist ein Vorschaufeature, das in einem zukünftigen Release entfernt werden kann. # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use.plural={0} sind ein Vorschaufeature, das in einem zukünftigen Release entfernt werden kann. # 0: file object (classfile), 1: string (expected version) +# lint: preview compiler.warn.preview.feature.use.classfile=Klassendatei für {0} verwendet Vorschaufeatures von Java SE {1}. compiler.misc.feature.modules=Module @@ -2515,6 +2630,7 @@ compiler.err.expected.module="module" erwartet compiler.err.module.not.found=Modul nicht gefunden: {0} # 0: symbol +# lint: module compiler.warn.module.not.found=Modul nicht gefunden: {0} # 0: name @@ -2584,6 +2700,7 @@ compiler.err.service.implementation.no.args.constructor.not.public=Der "no argum compiler.err.package.empty.or.not.found=Package ist leer oder nicht vorhanden: {0} # 0: symbol +# lint: opens compiler.warn.package.empty.or.not.found=Package ist leer oder nicht vorhanden: {0} compiler.err.no.output.dir=Kein Klassenausgabeverzeichnis angegeben @@ -2644,6 +2761,7 @@ compiler.warn.bad.name.for.option=Ungültiger Name im Wert für {0}-Option: "{1} compiler.err.bad.name.for.option=Ungültiger Name im Wert für {0}-Option: "{1}" # 0: option name, 1: symbol +# lint: options compiler.warn.module.for.option.not.found=Modulname in {0}-Option nicht gefunden: {1} compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATH kann nur beim Kompilieren des unbenannten Moduls oder beim Kompilieren im Kontext eines automatischen Moduls verwendet werden @@ -2654,6 +2772,7 @@ compiler.err.add.exports.with.release=Export eines Packages aus Systemmodul {0} # 0: symbol compiler.err.add.reads.with.release=Hinzufügen von Lese-Edges für Systemmodul {0} ist mit --release nicht zulässig +# lint: options compiler.warn.addopens.ignored=--add-opens hat zur Kompilierungszeit keine Auswirkungen compiler.misc.locn.module_source_path=Modulquellpfad @@ -2675,12 +2794,16 @@ compiler.err.invalid.module.specifier=Modulbezeichner nicht zulässig: {0} compiler.warn.service.provided.but.not.exported.or.used=Serviceschnittstelle angegeben, aber nicht exportiert oder verwendet # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible={0} {1} in Modul {2} ist nicht zugänglich für Clients, die dieses Modul benötigen # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported={0} {1} in Modul {2} wird nicht exportiert # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.not.required.transitive={0} {1} in Modul {2} wird nicht indirekt mit "requires transitive" exportiert # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported.qualified={0} {1} in Modul {2} ist möglichweise nicht für alle Clients, die dieses Modul benötigen, sichtbar ### @@ -2712,7 +2835,10 @@ compiler.misc.is.a.type.variable=Darf keine Typvariablen enthalten: {0} compiler.misc.is.duplicated=Darf keine Duplikate enthalten: {0} # 0: type -compiler.misc.doesnt.extend.sealed=Unterklasse {0} muss verschlüsselte Klasse erweitern +compiler.misc.doesnt.extend.sealed=Klasse {0} muss verschlüsselte Klasse erweitern + +# 0: kind name, 1: type +compiler.misc.doesnt.implement.sealed={0} {1} muss verschlüsselte Klasse erweitern compiler.misc.must.not.be.same.class=Unzulässige Selbstreferenz in PERMITS-Klausel @@ -2912,9 +3038,14 @@ compiler.err.deconstruction.pattern.var.not.allowed=Dekonstruktionsmuster könne compiler.err.incorrect.number.of.nested.patterns=Falsche Anzahl verschachtelter Muster\nErforderlich: {0}\nGefunden: {1} # 0: kind name, 1: symbol +# lint: preview compiler.warn.declared.using.preview={0} {1} ist mit einem Vorschaufeature deklariert, das in einem zukünftigen Release entfernt werden kann. +# lint: identity compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=Versuch der Synchronisierung für eine Instanz einer wertbasierten Klasse +# lint: identity +compiler.warn.attempt.to.use.value.based.where.identity.expected=Verwendung einer wertbasierten Klasse mit einem Vorgang, der eine zuverlässige Identität erwartet + # 0: type compiler.err.enclosing.class.type.non.denotable=Einschließender Klassentyp: {0}\nist nicht deklarierbar. Führen Sie das Casting in einen deklarierbaren Typ aus diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index 9ab2862407f..aa501fd6c11 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -251,7 +251,7 @@ compiler.misc.no.suitable.functional.intf.inst={0}の機能インタフェース compiler.misc.bad.intersection.target.for.functional.expr=ラムダまたはメソッド参照の交差タイプ・ターゲットが不正です\n{0} # 0: symbol or type -compiler.misc.not.an.intf.component=コンポーネント・タイプ{0}はインタフェースではありません +compiler.misc.not.an.intf.component=コンポーネント・タイプ{0}はインタフェースまたはjava.lang.Objectではありません # 0: kind name, 1: message segment compiler.err.invalid.mref={0}参照が無効です\n{1} @@ -389,9 +389,9 @@ compiler.err.duplicate.class=クラス{0}が重複しています # 0: string compiler.err.bad.file.name=不正なファイル名: {0} -compiler.err.implicit.class.should.not.have.package.declaration=暗黙的に宣言されたクラスにパッケージ宣言を含めることはできません +compiler.err.implicit.class.should.not.have.package.declaration=コンパクト・ソース・ファイルにパッケージ宣言を含めることはできません -compiler.err.implicit.class.does.not.have.main.method=暗黙的に宣言されたクラスにvoid main()またはvoid main(String[] args)という形式のmainメソッドがありません +compiler.err.implicit.class.does.not.have.main.method=コンパクト・ソース・ファイルにvoid main()またはvoid main(String[] args)という形式のmainメソッドがありません # 0: name, 1: name compiler.err.same.binary.name=クラス: {0}と{1}のバイナリ名が同じです @@ -501,6 +501,8 @@ compiler.err.illegal.combination.of.modifiers=修飾子{0}と{1}の組合せは compiler.err.illegal.enum.static.ref=初期化子からstaticフィールドへの参照が不正です +compiler.err.illegal.char.literal.multiple.surrogates=文字リテラルに複数のUTF-16コード・ユニットが含まれています + compiler.err.illegal.esc.char=エスケープ文字が不正です compiler.err.illegal.forward.ref=前方参照が不正です @@ -511,8 +513,10 @@ compiler.err.not.in.profile={0}はプロファイル''{1}''で使用できませ # 0: symbol compiler.warn.forward.ref=初期化される前の変数''{0}''を参照しようとしました +# lint: this-escape compiler.warn.possible.this.escape=サブクラスが初期化される前の''this''エスケープの可能性があります +# lint: this-escape compiler.warn.possible.this.escape.location=事前の''this''エスケープはこの呼び出しで出現する可能性があります compiler.err.illegal.self.ref=初期化子内の自己参照 @@ -527,8 +531,10 @@ compiler.err.illegal.line.end.in.char.lit=文字リテラルの行末が不正 compiler.err.illegal.text.block.open=テキスト・ブロックの開始区切り文字のシーケンスが無効です。行の終了文字がありません +# lint: text-blocks compiler.warn.inconsistent.white.space.indentation=空白のインデントに一貫性がありません +# lint: text-blocks compiler.warn.trailing.white.space.will.be.removed=末尾の空白は除去されます compiler.err.illegal.nonascii.digit=不正な非ASCII数字です @@ -1112,6 +1118,7 @@ compiler.err.cant.read.file={0}を読み込めません compiler.err.plugin.not.found=プラグインが見つかりません: {0} # 0: path +# lint: path compiler.warn.locn.unknown.file.on.module.path=モジュール・パスのファイルが不明です: {0} @@ -1131,6 +1138,7 @@ compiler.err.locn.cant.get.module.name.for.jar={0}のモジュール名を判別 compiler.err.multi-module.outdir.cannot.be.exploded.module=複数モジュール・モードで、出力ディレクトリは展開したモジュールにすることはできません: {0} # 0: path +# lint: path compiler.warn.outdir.is.in.exploded.module=出力ディレクトリは展開したモジュール内です: {0} # 0: file object @@ -1182,6 +1190,7 @@ compiler.misc.x.print.rounds=往復{0}:\n\t入力ファイル: {1}\n\t注釈: {2 compiler.warn.file.from.future=ファイル{0}の変更日が将来の日付です # 0: path +# lint: output-file-clash compiler.warn.output.file.clash=出力ファイルへの書込みが複数回ありました: {0} ##### @@ -1335,51 +1344,67 @@ compiler.warn.warning=警告:\u0020 compiler.warn.lintOption=[{0}]\u0020 # 0: symbol +# lint: serial compiler.warn.constant.SVUID=serialVersionUIDはクラス{0}の定数である必要があります +# lint: dangling-doc-comments compiler.warn.dangling.doc.comment=どの宣言にもドキュメンテーション・コメントが添付されていません # 0: path +# lint: path compiler.warn.dir.path.element.not.found=不正なパス要素"{0}": そのディレクトリは存在しません # 0: file name +# lint: path compiler.warn.dir.path.element.not.directory=不正なパス要素"{0}": ディレクトリは存在しません # 0: symbol, 1: symbol, 2: symbol +# lint: missing-explicit-ctor compiler.warn.missing-explicit-ctor=エクスポートされたパッケージ{1}のクラス{0}は明示的なコンストラクタを宣言しないため、デフォルト・コンストラクタをモジュール{2}のクライアントに公開します +# lint: strictfp compiler.warn.strictfp=リリース17以降、すべての浮動小数点式は厳密に評価され、''strictfp''は必要ありません +# lint: finally compiler.warn.finally.cannot.complete=finally節が正常に完了できません # 0: name +# lint: module compiler.warn.poor.choice.for.module.name=モジュール名コンポーネント{0}の末尾は数字にしないでください # 0: string +# lint: incubating compiler.warn.incubating.modules=実験的なモジュールを使用しています: {0} # 0: symbol, 1: symbol +# lint: deprecation compiler.warn.has.been.deprecated={1}の{0}は推奨されません # 0: symbol, 1: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal={1}の{0}は推奨されておらず、削除用にマークされています # 0: symbol +# lint: preview compiler.warn.is.preview={0}はプレビューAPIであり、今後のリリースで削除される可能性があります。 # 0: symbol compiler.err.is.preview={0}はプレビューAPIであり、デフォルトで無効になっています。\n(プレビューAPIを有効にするには--enable-previewを使用します) # 0: symbol +# lint: preview compiler.warn.is.preview.reflective={0}はリフレクティブ・プレビューAPIであり、今後のリリースで削除される可能性があります。 # 0: symbol, 1: symbol +# lint: restricted compiler.warn.restricted.method={0}.{1}は制限されたメソッドです。\n(制限されたメソッドは安全ではありません。不適切に使用した場合、Javaランタイムがクラッシュまたはメモリーが破損する場合があります) # 0: symbol +# lint: deprecation compiler.warn.has.been.deprecated.module=モジュール{0}は推奨されません # 0: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal.module=モジュール{0}は推奨されておらず、削除用にマークされています # 0: symbol @@ -1388,10 +1413,13 @@ compiler.warn.sun.proprietary={0}は内部所有のAPIであり、今後のリ compiler.warn.illegal.char.for.encoding=この文字は、エンコーディング{0}にマップできません # 0: symbol +# lint: serial compiler.warn.improper.SVUID=serialVersionUIDは、クラス{0}にstatic finalを宣言する必要があります +# lint: serial compiler.warn.improper.SPF=serialPersistentFieldsを有効にするには、private static finalとして宣言する必要があります +# lint: serial compiler.warn.SPF.null.init=nullに初期化するとserialPersistentFieldsは無効になります。\nフィールドがないことを示すには、空の配列に初期化します @@ -1405,82 +1433,111 @@ compiler.warn.unreachable.catch=catch句に移すことができません\nス compiler.warn.unreachable.catch.1=catch句に移すことができません\nスローされたタイプ{0}はすでに捕捉されています # 0: symbol +# lint: serial compiler.warn.long.SVUID=serialVersionUIDは、クラス{0}のlong型である必要があります +# lint: serial compiler.warn.OSF.array.SPF=serialPersistentFieldsを有効にするには、タイプをjava.io.ObjectStreamField[]にする必要があります # 0: symbol +# lint: serial compiler.warn.missing.SVUID=直列化可能なクラス{0}には、serialVersionUIDが定義されていません # 0: name +# lint: serial compiler.warn.serializable.missing.access.no.arg.ctor=シリアライズ不可のスーパークラス{0}で引数なしのコンストラクタにアクセスできません # 0: name +# lint: serial compiler.warn.serial.method.not.private=シリアライズ関連メソッド{0}はprivateとして宣言されていません # 0: name +# lint: serial compiler.warn.serial.concrete.instance.method=シリアライズ関連メソッド{0}を有効にするには、concreteインスタンス・メソッドである必要があります。abstractでもstaticでもありません # 0: name +# lint: serial compiler.warn.serial.method.static=シリアライズ関連メソッド{0}がstaticとして宣言されています。有効にするには、かわりにインスタンス・メソッドにする必要があります # 0: name +# lint: serial compiler.warn.serial.method.no.args=有効にするには、シリアライズ関連メソッド{0}にパラメータを指定しないでください # 0: name, 1: number +# lint: serial compiler.warn.serial.method.one.arg=有効にするには、シリアライズ関連メソッド{0}に、{1}のパラメータではなく、パラメータを1つのみ指定する必要があります # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.parameter.type=有効にするには、シリアライズ関連メソッド{0}の1つのパラメータに、型{2}ではなく、型{1}を指定する必要があります # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.unexpected.return.type=シリアライズ関連メソッド{0}は、必要な型{2}ではなく、{1}の戻り型で宣言されています。\n宣言されているように、メソッドはシリアライズが無効になります # 0: name, 1: type +# lint: serial compiler.warn.serial.method.unexpected.exception=シリアライズ関連メソッド{0}は予期しない型{1}をスローするように宣言されています +# lint: serial compiler.warn.ineffectual.serial.field.interface=serialPersistentFieldsはインタフェースで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.serial.field.enum=シリアライズ関連フィールド{0}は列挙クラスで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.enum=シリアライズ関連メソッド{0}は列挙クラスで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.extern.method.enum=外部化関連メソッド{0}は列挙クラスで有効ではありません +# lint: serial compiler.warn.ineffectual.serial.field.record=serialPersistentFieldsはレコード・クラスで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.record=シリアライズ関連メソッド{0}はレコード・ラスで有効ではありません # 0: string +# lint: serial compiler.warn.ineffectual.externalizable.method.record=外部化関連メソッド{0}はレコード・クラスで有効ではありません # 0: name +# lint: serial compiler.warn.ineffectual.serial.method.externalizable=シリアライズ関連メソッド{0}は外部化可能なクラスで有効ではありません +# lint: serial compiler.warn.ineffectual.serial.field.externalizable=serialPersistentFieldsは外部化可能なクラスで有効ではありません +# lint: serial compiler.warn.externalizable.missing.public.no.arg.ctor=外部化可能なクラスには引数なしでパブリックのコンストラクタが必要です +# lint: serial compiler.warn.non.serializable.instance.field=直列化可能なクラスの常駐インスタンス・フィールドは直列不可タイプで宣言されています # 0: type +# lint: serial compiler.warn.non.serializable.instance.field.array=直列化可能なクラスの常駐インスタンス・フィールドは、直列不可のベース・コンポーネント・タイプ{0}を持つ配列で宣言されています +# lint: serial compiler.warn.non.private.method.weaker.access=インタフェースでprivateとして宣言されたシリアライズ関連メソッドによって、\nそのインタフェースを実装するクラスがメソッドをprivateとして宣言できなくなります +# lint: serial compiler.warn.default.ineffective=インタフェースのシリアライズ関連のデフォルト・メソッドは、クラスを実装するためのシリアライズで実行されません # 0: symbol, 1: symbol, 2: symbol, 3: symbol +# lint: overloads compiler.warn.potentially.ambiguous.overload={1}内の{0}は{3}内の{2}と矛盾する可能性があります # 0: message segment +# lint: overrides compiler.warn.override.varargs.missing={0}。オーバーライドされたメソッドには''...''がありません # 0: message segment +# lint: overrides compiler.warn.override.varargs.extra={0}。オーバーライドしているメソッドには''...''がありません # 0: message segment @@ -1490,11 +1547,14 @@ compiler.warn.override.bridge={0}。オーバーライドされたメソッド compiler.warn.pkg-info.already.seen=package-info.javaファイルがすでにパッケージ{0}用に表示されています # 0: path +# lint: path compiler.warn.path.element.not.found=不正なパス要素"{0}": そのファイルまたはディレクトリはありません +# lint: fallthrough compiler.warn.possible.fall-through.into.case=caseにfall-throughする可能性があります # 0: type +# lint: cast compiler.warn.redundant.cast={0}への冗長なキャストです # 0: number @@ -1507,15 +1567,19 @@ compiler.warn.big.major.version={0}: メジャー・バージョン{1}は、こ compiler.warn.invalid.utf8.in.classfile={0}: クラス・ファイルに無効なUTF-8が含まれています: {1} # 0: kind name, 1: symbol +# lint: static compiler.warn.static.not.qualified.by.type=static {0}は式ではなく型名{1}で修飾する必要があります # 0: kind name +# lint: static compiler.warn.static.not.qualified.by.type2=static {0}を匿名クラスのメンバーとして使用しないでください # 0: string, 1: fragment +# lint: options compiler.warn.source.no.bootclasspath=ブートストラップ・クラス・パスが-source {0}と一緒に設定されていません\n{1} # 0: string, 1: fragment +# lint: options compiler.warn.source.no.system.modules.path=システム・モジュールの場所が-source {0}と一緒に設定されていません\n{1} # 0: string @@ -1531,9 +1595,11 @@ compiler.misc.source.no.bootclasspath.with.target=ブートストラップ・ク compiler.misc.source.no.system.modules.path.with.target=システム・モジュールの場所を設定しないと、クラス・ファイルがJDK {0}で実行できない場合があります\nシステム・モジュールの場所を自動的に設定するため、-source {0} -target {1}のかわりに--release {0}をお薦めします # 0: string +# lint: options compiler.warn.option.obsolete.source=ソース値{0}は廃止されていて、今後のリリースで削除される予定です # 0: target +# lint: options compiler.warn.option.obsolete.target=ターゲット値{0}は廃止されていて、今後のリリースで削除される予定です # 0: string, 1: string @@ -1542,13 +1608,17 @@ compiler.err.option.removed.source=ソース・オプション{0}は現在サポ # 0: target, 1: target compiler.err.option.removed.target=ターゲット・オプション{0}は現在サポートされていません。{1}以降を使用してください。 +# lint: options compiler.warn.option.obsolete.suppression=廃止されたオプションについての警告を表示しないようにするには、-Xlint:オプションを使用します。 # 0: name, 1: number, 2: number, 3: number, 4: number +# lint: classfile compiler.warn.future.attr=バージョン{1}.{2}のクラス・ファイルで導入された{0}属性は、バージョン{3}.{4}のクラス・ファイルでは無視されます +# lint: requires-automatic compiler.warn.requires.automatic=自動モジュールにはディレクティブが必要です +# lint: requires-transitive-automatic compiler.warn.requires.transitive.automatic=自動モジュールには推移的ディレクティブが必要です # Warnings related to annotation processing @@ -1556,40 +1626,50 @@ compiler.warn.requires.transitive.automatic=自動モジュールには推移的 compiler.warn.proc.package.does.not.exist=パッケージ{0}は存在しません # 0: string +# lint: processing compiler.warn.proc.file.reopening=''{0}''用のファイルを複数回作成しようとしています # 0: string +# lint: processing compiler.warn.proc.type.already.exists=タイプ''{0}''のファイルはすでにソース・パスまたはクラスパスに存在します # 0: string +# lint: processing compiler.warn.proc.type.recreate=タイプ''{0}''のファイルを複数回作成しようとしています # 0: string +# lint: processing compiler.warn.proc.illegal.file.name=無効な名前''{0}''のファイルは作成できません。 # 0: string, 1: string +# lint: processing compiler.warn.proc.suspicious.class.name=名前が{1}で終わる型のファイルを作成しています: ''{0}'' # 0: string compiler.warn.proc.file.create.last.round=最後に作成されたタイプ''{0}''のファイルは注釈処理に渡されません。 # 0: string, 1: string +# lint: processing compiler.warn.proc.malformed.supported.string=プロセッサ''{1}''が返したサポートされる注釈インタフェースの文字列''{0}''が不正です # 0: set of string +# lint: processing compiler.warn.proc.annotations.without.processors=これらの注釈を要求するプロセッサはありませんでした: {0} # 0: source version, 1: string, 2: string compiler.warn.proc.processor.incompatible.source.version=注釈プロセッサ''{1}''から-source ''{2}''より小さいソース・バージョン''{0}''がサポートされています # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.option.name=重複するサポート対象オプション''{0}''が注釈プロセッサ''{1}''によって返されました # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.supported.annotation=重複するサポート対象注釈インタフェース''{0}''が注釈プロセッサ''{1}''によって返されました # 0: string +# lint: processing compiler.warn.proc.redundant.types.with.wildcard=注釈プロセッサ''{0}''は''*''と他の注釈インタフェースを重複してサポートします compiler.warn.proc.proc-only.requested.no.procs=コンパイルなしの注釈処理がリクエストされましたが、プロセッサが見つかりませんでした。 @@ -1608,42 +1688,56 @@ compiler.warn.proc.unclosed.type.files=タイプ''{0}''のファイルが閉じ # 0: string compiler.warn.proc.unmatched.processor.options=次のオプションはどのプロセッサでも認識されませんでした: ''{0}'' +# lint: try compiler.warn.try.explicit.close.call=自動クローズ可能なリソースにおけるclose()の明示的呼出し # 0: symbol +# lint: try compiler.warn.try.resource.not.referenced=自動クローズ可能なリソース{0}は対応するtry文の本体では参照されません # 0: type +# lint: try compiler.warn.try.resource.throws.interrupted.exc=自動クローズ可能なリソース{0}に、InterruptedExceptionをスローする可能性があるメンバー・メソッドclose()があります +# lint: unchecked compiler.warn.unchecked.assign={0}から{1}への無検査代入です # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.assign.to.var=raw型{1}のメンバーとして変数{0}への無検査代入です # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.call.mbr.of.raw.type=raw型{1}のメンバーとしての{0}への無検査呼出しです +# lint: unchecked compiler.warn.unchecked.cast.to.type=型{0}への無検査キャストです # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol +# lint: unchecked compiler.warn.unchecked.meth.invocation.applied=無検査メソッド呼出し: {4} {5}の{0} {1}は指定された型に適用されます\n期待値: {2}\n検出値: {3} # 0: type +# lint: unchecked compiler.warn.unchecked.generic.array.creation=型{0}の可変引数パラメータに対する総称型配列の無検査作成です # 0: type +# lint: unchecked compiler.warn.unchecked.varargs.non.reifiable.type=パラメータ化された可変引数型{0}からのヒープ汚染の可能性があります # 0: symbol +# lint: varargs compiler.warn.varargs.unsafe.use.varargs.param=可変引数メソッドは、型情報保持可能でない可変引数パラメータ{0}からのヒープ汚染の原因となる可能性があります +# lint: dep-ann compiler.warn.missing.deprecated.annotation=推奨されない項目は@Deprecatedで注釈が付けられていません # 0: kind name +# lint: deprecation compiler.warn.deprecated.annotation.has.no.effect=@Deprecated注釈は、この{0}宣言には影響しません # 0: string +# lint: path compiler.warn.invalid.path=ファイル名が無効です: {0} compiler.warn.doclint.not.available=使用可能なdoclintのサービス・プロバイダはありません @@ -1653,22 +1747,28 @@ compiler.err.invalid.path=ファイル名が無効です: {0} # 0: path +# lint: path compiler.warn.invalid.archive.file=パス上の予期しないファイル: {0} # 0: path +# lint: path compiler.warn.unexpected.archive.file=アーカイブ・ファイルの予期しない拡張子: {0} # 0: path compiler.err.no.zipfs.for.archive=このファイルの処理に使用できるファイル・システム・プロバイダがありません: {0} +# lint: divzero compiler.warn.div.zero=ゼロで除算 +# lint: empty compiler.warn.empty.if=if以降が空の文です # 0: type, 1: name +# lint: classfile compiler.warn.annotation.method.not.found=タイプ''{0}''内に注釈メソッド''{1}()''が見つかりません # 0: type, 1: name, 2: message segment +# lint: classfile compiler.warn.annotation.method.not.found.reason=タイプ''{0}''内に注釈メソッド''{1}()''が見つかりません: {2} # 0: list of annotation, 1: symbol, 2: name, 3: message segment @@ -1681,6 +1781,7 @@ compiler.warn.unknown.enum.constant=不明な列挙型定数です{1}.{2} compiler.warn.unknown.enum.constant.reason=不明な列挙型定数です{1}.{2}\n理由: {3} # 0: type, 1: type +# lint: rawtypes compiler.warn.raw.class.use=raw型が見つかりました: {0}\n汎用クラス{1}の型引数がありません compiler.warn.diamond.redundant.args=新しい式の型引数が重複しています(かわりにダイヤモンド演算子を使用します)。 @@ -1692,12 +1793,15 @@ compiler.warn.potential.lambda.found=この匿名内部クラスをラムダ式 compiler.warn.method.redundant.typeargs=メソッド呼出しの型引数が重複しています。 # 0: symbol, 1: message segment +# lint: varargs compiler.warn.varargs.redundant.trustme.anno={0}注釈が冗長です。{1} # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.element=直列化可能要素からメンバー{0}へのアクセスは、信頼できないコードからパブリックにアクセス可能である可能性があります # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.lambda=直列化可能ラムダからメンバー{0}へのアクセスは、信頼できないコードからパブリックにアクセス可能である可能性があります ##### @@ -1810,9 +1914,11 @@ compiler.misc.bad.enclosing.class={0}の内部クラスが不正です: {1} compiler.misc.bad.enclosing.method=クラス{0}の囲んでいるメソッド属性が不正です # 0: file name +# lint: classfile compiler.warn.runtime.visible.invisible.param.annotations.mismatch={0}内のRuntimeVisibleParameterAnnotations属性およびRuntimeInvisibleParameterAnnotations属性内のパラメータの長さが一致しません。両方の属性を無視します # 0: file name +# lint: classfile compiler.warn.runtime.invisible.parameter.annotations={0}内のRuntimeVisibleParameterAnnotationsおよびRuntimeInvisibleParameterAnnotations属性をメソッドのパラメータにマップできません compiler.misc.bad.const.pool.tag=定数プール・タグ{0}が不正です @@ -1904,6 +2010,7 @@ compiler.err.prob.found.req=不適合な型: {0} compiler.misc.prob.found.req=不適合な型: {0} # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.prob.found.req={0}\n期待値: {2}\n検出値: {1} # 0: type, 1: type @@ -1913,6 +2020,7 @@ compiler.misc.inconvertible.types={0}を{1}に変換できません: compiler.misc.possible.loss.of.precision=精度が失われる可能性がある{0}から{1}への変換 # 0: type, 1: type +# lint: lossy-conversions compiler.warn.possible.loss.of.precision=複合代入における{0}から{1}への暗黙的キャストは、精度が失われる可能性があります compiler.misc.unchecked.assign=無検査変換 @@ -2035,6 +2143,7 @@ compiler.misc.varargs.argument.mismatch=可変引数の不一致: {0} ##### # 0: symbol or type, 1: file name +# lint: auxiliaryclass compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file={1}の補助クラス{0}にソース・ファイル外からアクセスできません ## The first argument ({0}) is a "kindname". @@ -2174,12 +2283,15 @@ compiler.err.override.weaker.access={0}\n({1})より弱いアクセス権限を compiler.err.override.incompatible.ret={0}\n戻り値の型{1}は{2}と互換性がありません # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.override.unchecked.ret={0}\n戻り値の型は{1}から{2}への無検査変換が必要です # 0: message segment, 1: type +# lint: unchecked compiler.warn.override.unchecked.thrown={0}\nオーバーライドされたメソッドは{1}をスローしません # 0: symbol +# lint: overrides compiler.warn.override.equals.but.not.hashcode=クラス{0}はequalsをオーバーライドしますが、このクラスも、また、いかなるスーパークラスも、hashCodeメソッドをオーバーライドしません ## The following are all possible strings for the first argument ({0}) of the @@ -2245,12 +2357,15 @@ compiler.err.preview.feature.disabled.plural={0}はプレビュー機能であ compiler.err.preview.feature.disabled.classfile={0}のクラス・ファイルはJava SE {1}のプレビュー機能を使用します。\n(プレビュー機能を含むクラス・ファイルをロードできるようにするには、--enable-previewを使用します) # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use={0}はプレビュー機能であり、今後のリリースで削除される可能性があります。 # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use.plural={0}はプレビュー機能であり、今後のリリースで削除される可能性があります。 # 0: file object (classfile), 1: string (expected version) +# lint: preview compiler.warn.preview.feature.use.classfile={0}のクラス・ファイルはJava SE {1}のプレビュー機能を使用します。 compiler.misc.feature.modules=モジュール @@ -2515,6 +2630,7 @@ compiler.err.expected.module=''モジュール''が必要です compiler.err.module.not.found=モジュールが見つかりません: {0} # 0: symbol +# lint: module compiler.warn.module.not.found=モジュールが見つかりません: {0} # 0: name @@ -2584,6 +2700,7 @@ compiler.err.service.implementation.no.args.constructor.not.public=サービス compiler.err.package.empty.or.not.found=パッケージは空であるか、または存在しません {0} # 0: symbol +# lint: opens compiler.warn.package.empty.or.not.found=パッケージは空であるか、または存在しません {0} compiler.err.no.output.dir=クラス出力ディレクトリが指定されていません @@ -2644,6 +2761,7 @@ compiler.warn.bad.name.for.option={0}オプションの値に含まれる名前 compiler.err.bad.name.for.option={0}オプションの値に含まれる名前が不正です: ''{1}'' # 0: option name, 1: symbol +# lint: options compiler.warn.module.for.option.not.found={0}オプション内にモジュール名が見つかりません: {1} compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATHは、名前のないモジュールのコンパイル時または自動モジュールのコンテキストでのコンパイル時のみ使用できます @@ -2654,6 +2772,7 @@ compiler.err.add.exports.with.release=システム・モジュール{0}からの # 0: symbol compiler.err.add.reads.with.release=システム・モジュール{0}の読取りエッジの追加は--releaseを指定して実行できません +# lint: options compiler.warn.addopens.ignored=--add-opensは、コンパイル時には無効です compiler.misc.locn.module_source_path=モジュール・ソース・パス @@ -2675,12 +2794,16 @@ compiler.err.invalid.module.specifier=モジュール指定子は許可されま compiler.warn.service.provided.but.not.exported.or.used=サービス・インタフェースが指定されましたが、エクスポートまたは使用されていません # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible=モジュール{2}の{0} {1}は、このモジュールを必要とするクライアントからアクセスできません # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported=モジュール{2}の{0} {1}はエクスポートされません # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.not.required.transitive=モジュール{2}の{0} {1}は、''requires transitive''を使用して間接的にエクスポートされません # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported.qualified=モジュール{2}の{0} {1}は、このモジュールを必要とするすべてのクライアントに表示されない可能性があります ### @@ -2712,7 +2835,10 @@ compiler.misc.is.a.type.variable=型変数を含めることはできません: compiler.misc.is.duplicated=重複を含めることはできません: {0} # 0: type -compiler.misc.doesnt.extend.sealed=サブクラス{0}はシール・クラスを拡張する必要があります +compiler.misc.doesnt.extend.sealed=クラス{0}はシール・クラスを拡張する必要があります + +# 0: kind name, 1: type +compiler.misc.doesnt.implement.sealed={0} {1}はシール・インタフェースを拡張する必要があります compiler.misc.must.not.be.same.class=permits句の自己参照が不正です @@ -2912,9 +3038,14 @@ compiler.err.deconstruction.pattern.var.not.allowed=デコンストラクショ compiler.err.incorrect.number.of.nested.patterns=ネスト・パターンの数が正しくありません\n期待値: {0}\n検出値: {1} # 0: kind name, 1: symbol +# lint: preview compiler.warn.declared.using.preview={0} {1}はプレビュー機能を使用して宣言されており、今後のリリースで削除される可能性があります。 +# lint: identity compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=値ベース・クラスのインスタンスで同期しようとしました +# lint: identity +compiler.warn.attempt.to.use.value.based.where.identity.expected=信頼できるアイデンティティを必要とする操作での値ベース・クラスの使用 + # 0: type compiler.err.enclosing.class.type.non.denotable=包含するクラス型: {0}\nは非型指定です。型指定型にキャストしてみてください diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index 52a6ec23e51..d25110f6532 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -251,7 +251,7 @@ compiler.misc.no.suitable.functional.intf.inst=无法推断{0}的函数接口描 compiler.misc.bad.intersection.target.for.functional.expr=lambda 或方法引用的交叉类型目标错误\n{0} # 0: symbol or type -compiler.misc.not.an.intf.component=组件类型{0}不是接口 +compiler.misc.not.an.intf.component=组件类型 {0} 不是接口或 java.lang.Object # 0: kind name, 1: message segment compiler.err.invalid.mref={0}引用无效\n{1} @@ -389,9 +389,9 @@ compiler.err.duplicate.class=类重复: {0} # 0: string compiler.err.bad.file.name=文件名错误:{0} -compiler.err.implicit.class.should.not.have.package.declaration=隐式声明的类不应有程序包声明 +compiler.err.implicit.class.should.not.have.package.declaration=压缩源文件不应有程序包声明 -compiler.err.implicit.class.does.not.have.main.method=隐式声明的类没有 void main() 或 void main(String[] args) 形式的 main 方法 +compiler.err.implicit.class.does.not.have.main.method=压缩源文件没有 void main() 或 void main(String[] args) 形式的 main 方法 # 0: name, 1: name compiler.err.same.binary.name=类:{0} 和 {1} 具有相同的二进制名称 @@ -501,6 +501,8 @@ compiler.err.illegal.combination.of.modifiers=非法的修饰符组合: {0}和{1 compiler.err.illegal.enum.static.ref=初始化程序中对静态字段的引用不合法 +compiler.err.illegal.char.literal.multiple.surrogates=字符文字包含多个 UTF-16 代码单元 + compiler.err.illegal.esc.char=非法逃逸 符 compiler.err.illegal.forward.ref=非法前向引用 @@ -511,8 +513,10 @@ compiler.err.not.in.profile={0}在配置文件 ''{1}'' 中不可用 # 0: symbol compiler.warn.forward.ref=先引用变量 ''{0}'', 然后再对其初始化 +# lint: this-escape compiler.warn.possible.this.escape=可能在完全初始化子类之前逃逸了 ''this'' +# lint: this-escape compiler.warn.possible.this.escape.location=此处以前可能通过调用逃逸 了 ''this'' compiler.err.illegal.self.ref=初始化程序中存在自引用 @@ -527,8 +531,10 @@ compiler.err.illegal.line.end.in.char.lit=字符文字的行结尾不合法 compiler.err.illegal.text.block.open=文本块起始分隔符序列非法,缺少行终止符 +# lint: text-blocks compiler.warn.inconsistent.white.space.indentation=空格缩进不一致 +# lint: text-blocks compiler.warn.trailing.white.space.will.be.removed=将删除尾随空格 compiler.err.illegal.nonascii.digit=非法的非 ASCII 数字 @@ -1112,6 +1118,7 @@ compiler.err.cant.read.file=无法读取: {0} compiler.err.plugin.not.found=找不到插件: {0} # 0: path +# lint: path compiler.warn.locn.unknown.file.on.module.path=模块路径中的未知文件: {0} @@ -1131,6 +1138,7 @@ compiler.err.locn.cant.get.module.name.for.jar=无法确定 {0} 的模块名称 compiler.err.multi-module.outdir.cannot.be.exploded.module=在多模块模式下, 输出目录不能是展开的模块: {0} # 0: path +# lint: path compiler.warn.outdir.is.in.exploded.module=输出目录位于展开的模块中: {0} # 0: file object @@ -1182,6 +1190,7 @@ compiler.misc.x.print.rounds=循环 {0}:\n\t输入文件: {1}\n\t批注: {2}\n\t compiler.warn.file.from.future=文件 {0} 的修改日期是未来的日期 # 0: path +# lint: output-file-clash compiler.warn.output.file.clash=多次写入输出文件:{0} ##### @@ -1335,51 +1344,67 @@ compiler.warn.warning=警告:\u0020 compiler.warn.lintOption=[{0}]\u0020 # 0: symbol +# lint: serial compiler.warn.constant.SVUID=serialVersionUID 在类{0}中必须是常量 +# lint: dangling-doc-comments compiler.warn.dangling.doc.comment=文档注释未附加到任何声明 # 0: path +# lint: path compiler.warn.dir.path.element.not.found=错误的路径元素 "{0}": 没有这种目录 # 0: file name +# lint: path compiler.warn.dir.path.element.not.directory=错误的路径元素 "{0}": 不是目录 # 0: symbol, 1: symbol, 2: symbol +# lint: missing-explicit-ctor compiler.warn.missing-explicit-ctor=导出的程序包 {1} 中的类 {0} 未声明显式构造器,因此将向模块 {2} 的客户机公开默认构造器 +# lint: strictfp compiler.warn.strictfp=从发行版 17 开始,所有浮点表达式都经过严格计算,不需要 ''strictfp'' +# lint: finally compiler.warn.finally.cannot.complete=finally 子句无法正常完成 # 0: name +# lint: module compiler.warn.poor.choice.for.module.name=模块名称组成部分 {0} 应避免以数字结尾 # 0: string +# lint: incubating compiler.warn.incubating.modules=使用 incubating 模块: {0} # 0: symbol, 1: symbol +# lint: deprecation compiler.warn.has.been.deprecated={1}中的{0}已过时 # 0: symbol, 1: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal={1} 中的 {0} 已过时, 且标记为待删除 # 0: symbol +# lint: preview compiler.warn.is.preview={0} 是预览 API,可能会在未来发行版中删除。 # 0: symbol compiler.err.is.preview={0} 是预览 API,默认情况下处于禁用状态。\n(请使用 --enable-preview 以启用预览 API) # 0: symbol +# lint: preview compiler.warn.is.preview.reflective={0} 是反射预览 API,可能会在未来发行版中删除。 # 0: symbol, 1: symbol +# lint: restricted compiler.warn.restricted.method={0}.{1} 是受限制的方法。\n(受限制的方法不安全,如果使用不当,可能会导致 Java 运行时崩溃或内存损坏) # 0: symbol +# lint: deprecation compiler.warn.has.been.deprecated.module=模块 {0} 已过时 # 0: symbol +# lint: removal compiler.warn.has.been.deprecated.for.removal.module=模块 {0} 已过时, 且标记为待删除 # 0: symbol @@ -1388,10 +1413,13 @@ compiler.warn.sun.proprietary={0}是内部专用 API, 可能会在未来发行 compiler.warn.illegal.char.for.encoding=编码{0}的不可映射字符 # 0: symbol +# lint: serial compiler.warn.improper.SVUID=必须在类{0}中将 serialVersionUID 声明为 static final +# lint: serial compiler.warn.improper.SPF=serialPersistentFields 必须声明为 private static final 才能生效 +# lint: serial compiler.warn.SPF.null.init=serialPersistentFields 如果初始化为空值,则无效。\n请初始化为空数组以指示没有字段 @@ -1405,82 +1433,111 @@ compiler.warn.unreachable.catch=catch 子句无法访问\n已捕获到抛出的 compiler.warn.unreachable.catch.1=catch 子句无法访问\n已捕获到抛出的类型{0} # 0: symbol +# lint: serial compiler.warn.long.SVUID=serialVersionUID 在类{0}中必须是 long 类型 +# lint: serial compiler.warn.OSF.array.SPF=serialPersistentFields 的类型必须为 java.io.ObjectStreamField[] 才能生效 # 0: symbol +# lint: serial compiler.warn.missing.SVUID=可序列化类{0}没有 serialVersionUID 的定义 # 0: name +# lint: serial compiler.warn.serializable.missing.access.no.arg.ctor=无法访问第一个不可序列化超类 {0} 中的无参数构造器 # 0: name +# lint: serial compiler.warn.serial.method.not.private=与序列化相关的方法 {0} 未声明为 private # 0: name +# lint: serial compiler.warn.serial.concrete.instance.method=与序列化相关的方法 {0} 必须是具体的实例方法才能生效,既不能是抽象方法也不能是静态方法 # 0: name +# lint: serial compiler.warn.serial.method.static=与序列化相关的方法 {0} 声明为 static;必须改为实例方法才能有效 # 0: name +# lint: serial compiler.warn.serial.method.no.args=与序列化相关的方法 {0} 必须没有参数才能生效 # 0: name, 1: number +# lint: serial compiler.warn.serial.method.one.arg=与序列化相关的方法 {0} 必须只有一个参数(而非 {1} 个参数)才能生效 # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.parameter.type=与序列化相关的方法 {0} 的唯一参数的类型必须为 {1}(而非 {2})才能生效 # 0: name, 1: type, 2: type +# lint: serial compiler.warn.serial.method.unexpected.return.type=与序列化相关的方法 {0} 是用返回类型 {1}(而不是预期类型 {2})声明的。\n如声明的那样,该方法对序列化无效 # 0: name, 1: type +# lint: serial compiler.warn.serial.method.unexpected.exception=与序列化相关的方法 {0} 声明为抛出意外类型 {1} +# lint: serial compiler.warn.ineffectual.serial.field.interface=serialPersistentFields 在接口中无效 # 0: string +# lint: serial compiler.warn.ineffectual.serial.field.enum=与序列化相关的字段 {0} 在枚举类中无效 # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.enum=与序列化相关的方法 {0} 在枚举类中无效 # 0: string +# lint: serial compiler.warn.ineffectual.extern.method.enum=与外部化相关的方法 {0} 在枚举类中无效 +# lint: serial compiler.warn.ineffectual.serial.field.record=serialPersistentFields 在记录类中无效 # 0: string +# lint: serial compiler.warn.ineffectual.serial.method.record=与序列化相关的方法 {0} 在记录类中无效 # 0: string +# lint: serial compiler.warn.ineffectual.externalizable.method.record=与外部化相关的方法 {0} 在记录类中无效 # 0: name +# lint: serial compiler.warn.ineffectual.serial.method.externalizable=与序列化相关的方法 {0} 在可外部化的类中无效 +# lint: serial compiler.warn.ineffectual.serial.field.externalizable=serialPersistentFields 在可外部化的类中无效 +# lint: serial compiler.warn.externalizable.missing.public.no.arg.ctor=可外部化的类需要一个公共的无参数构造器 +# lint: serial compiler.warn.non.serializable.instance.field=可序列化类的非瞬时实例字段是用不可序列化的类型声明的 # 0: type +# lint: serial compiler.warn.non.serializable.instance.field.array=可序列化类的非瞬时实例字段是用具有不可序列化基本组件类型 {0} 的数组声明的 +# lint: serial compiler.warn.non.private.method.weaker.access=在接口中声明为 non-private 的序列化相关方法将阻止\n实现接口的类将方法声明为 private +# lint: serial compiler.warn.default.ineffective=实现类的序列化不会运行接口中与序列化相关的默认方法 # 0: symbol, 1: symbol, 2: symbol, 3: symbol +# lint: overloads compiler.warn.potentially.ambiguous.overload={1} 中的 {0} 可能与 {3} 中的 {2} 混淆 # 0: message segment +# lint: overrides compiler.warn.override.varargs.missing={0}; 被覆盖的方法没有 ''...'' # 0: message segment +# lint: overrides compiler.warn.override.varargs.extra={0}; 覆盖的方法缺少 ''...'' # 0: message segment @@ -1490,11 +1547,14 @@ compiler.warn.override.bridge={0}; 被覆盖的方法为 bridge 方法 compiler.warn.pkg-info.already.seen=已找到程序包{0}的 package-info.java 文件 # 0: path +# lint: path compiler.warn.path.element.not.found=错误的路径元素 "{0}": 没有这种文件或目录 +# lint: fallthrough compiler.warn.possible.fall-through.into.case=可能无法实现 case # 0: type +# lint: cast compiler.warn.redundant.cast=出现冗余的到{0}的转换 # 0: number @@ -1507,15 +1567,19 @@ compiler.warn.big.major.version={0}: 主版本 {1} 比 {2} 新, 此编译器支 compiler.warn.invalid.utf8.in.classfile={0}:类文件包含无效 UTF-8:{1} # 0: kind name, 1: symbol +# lint: static compiler.warn.static.not.qualified.by.type=static {0}应由类型名称{1}而不是表达式限定 # 0: kind name +# lint: static compiler.warn.static.not.qualified.by.type2=static {0} 不应用作匿名类的成员 # 0: string, 1: fragment +# lint: options compiler.warn.source.no.bootclasspath=未与 -source {0} 一起设置引导类路径\n{1} # 0: string, 1: fragment +# lint: options compiler.warn.source.no.system.modules.path=未与 -source {0} 一起设置系统模块的位置\n{1} # 0: string @@ -1531,9 +1595,11 @@ compiler.misc.source.no.bootclasspath.with.target=不设置引导类路径可能 compiler.misc.source.no.system.modules.path.with.target=不设置系统模块的位置可能会导致类文件无法在 JDK {0} 上运行\n建议使用 --release {0} 而不是 -source {0} -target {1},因为它会自动设置系统模块的位置 # 0: string +# lint: options compiler.warn.option.obsolete.source=源值 {0} 已过时,将在未来发行版中删除 # 0: target +# lint: options compiler.warn.option.obsolete.target=目标值 {0} 已过时,将在未来发行版中删除 # 0: string, 1: string @@ -1542,13 +1608,17 @@ compiler.err.option.removed.source=不再支持源选项 {0}。请使用 {1} 或 # 0: target, 1: target compiler.err.option.removed.target=不再支持目标选项 {0}。请使用 {1} 或更高版本。 +# lint: options compiler.warn.option.obsolete.suppression=要隐藏有关已过时选项的警告, 请使用 -Xlint:-options。 # 0: name, 1: number, 2: number, 3: number, 4: number +# lint: classfile compiler.warn.future.attr={1}.{2} 版类文件中引入的 {0} 属性在 {3}.{4} 版类文件中被忽略 +# lint: requires-automatic compiler.warn.requires.automatic=需要自动模块的指令 +# lint: requires-transitive-automatic compiler.warn.requires.transitive.automatic=需要自动模块的过渡指令 # Warnings related to annotation processing @@ -1556,40 +1626,50 @@ compiler.warn.requires.transitive.automatic=需要自动模块的过渡指令 compiler.warn.proc.package.does.not.exist=程序包{0}不存在 # 0: string +# lint: processing compiler.warn.proc.file.reopening=尝试多次为 ''{0}'' 创建文件 # 0: string +# lint: processing compiler.warn.proc.type.already.exists=类型 ''{0}'' 的文件已经存在于源路径或类路径中 # 0: string +# lint: processing compiler.warn.proc.type.recreate=尝试多次创建类型 ''{0}'' 的文件 # 0: string +# lint: processing compiler.warn.proc.illegal.file.name=无法创建带有非法名称 ''{0}'' 的文件。 # 0: string, 1: string +# lint: processing compiler.warn.proc.suspicious.class.name=正在为名称以{1}结尾的类型创建文件: ''{0}'' # 0: string compiler.warn.proc.file.create.last.round=将不对在最后一个循环中创建的类型为 ''{0}'' 的文件进行批注处理。 # 0: string, 1: string +# lint: processing compiler.warn.proc.malformed.supported.string=处理程序 ''{1}'' 为支持的批注接口返回格式错误的字符串 ''{0}'' # 0: set of string +# lint: processing compiler.warn.proc.annotations.without.processors=没有处理程序要使用以下任何批注: {0} # 0: source version, 1: string, 2: string compiler.warn.proc.processor.incompatible.source.version=来自批注处理程序 ''{1}'' 的受支持 source 版本 ''{0}'' 低于 -source ''{2}'' # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.option.name=批注处理程序 ''{1}'' 返回重复的支持的选项 ''{0}'' # 0: string, 1: string +# lint: processing compiler.warn.proc.duplicate.supported.annotation=批注处理程序 ''{1}'' 返回重复的受支持批注接口 ''{0}'' # 0: string +# lint: processing compiler.warn.proc.redundant.types.with.wildcard=批注处理程序 ''{0}'' 重复支持 ''*'' 和其他批注接口 compiler.warn.proc.proc-only.requested.no.procs=在未请求编译的情况下进行批注处理, 但找不到处理程序。 @@ -1608,42 +1688,56 @@ compiler.warn.proc.unclosed.type.files=类型 ''{0}'' 的文件未关闭; 将不 # 0: string compiler.warn.proc.unmatched.processor.options=以下选项未被任何处理程序识别: ''{0}'' +# lint: try compiler.warn.try.explicit.close.call=在可自动结束的资源上显式调用 close() # 0: symbol +# lint: try compiler.warn.try.resource.not.referenced=不能在相应的 try 语句的正文中引用可自动结束的资源{0} # 0: type +# lint: try compiler.warn.try.resource.throws.interrupted.exc=可自动关闭的资源{0}包含的成员方法 close() 可能抛出 InterruptedException +# lint: unchecked compiler.warn.unchecked.assign=未经检查的分配: 将{0}分配给{1} # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.assign.to.var=对作为原始类型{1}的成员的变量{0}的分配未经过检查 # 0: symbol, 1: type +# lint: unchecked compiler.warn.unchecked.call.mbr.of.raw.type=对作为原始类型{1}的成员的{0}的调用未经过检查 +# lint: unchecked compiler.warn.unchecked.cast.to.type=向类型{0}的转换未经过检查 # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol +# lint: unchecked compiler.warn.unchecked.meth.invocation.applied=方法调用未经过检查: 将{4} {5}中的{0} {1}应用到给定的类型\n需要: {2}\n找到: {3} # 0: type +# lint: unchecked compiler.warn.unchecked.generic.array.creation=对于类型为{0}的 varargs 参数, 泛型数组创建未经过检查 # 0: type +# lint: unchecked compiler.warn.unchecked.varargs.non.reifiable.type=参数化 vararg 类型{0}的堆可能已受污染 # 0: symbol +# lint: varargs compiler.warn.varargs.unsafe.use.varargs.param=Varargs 方法可能导致来自不可具体化 varargs 参数 {0} 的堆污染 +# lint: dep-ann compiler.warn.missing.deprecated.annotation=未使用 @Deprecated 对已过时的项目进行批注 # 0: kind name +# lint: deprecation compiler.warn.deprecated.annotation.has.no.effect=@Deprecated 批注对此 {0} 声明没有任何效果 # 0: string +# lint: path compiler.warn.invalid.path=无效文件名: {0} compiler.warn.doclint.not.available=没有 doclint 服务提供方可用 @@ -1653,22 +1747,28 @@ compiler.err.invalid.path=无效文件名: {0} # 0: path +# lint: path compiler.warn.invalid.archive.file=以下路径中存在意外的文件: {0} # 0: path +# lint: path compiler.warn.unexpected.archive.file=以下档案文件存在意外的扩展名: {0} # 0: path compiler.err.no.zipfs.for.archive=没有任何文件系统提供方可处理此文件: {0} +# lint: divzero compiler.warn.div.zero=除数为零 +# lint: empty compiler.warn.empty.if=if 之后没有语句 # 0: type, 1: name +# lint: classfile compiler.warn.annotation.method.not.found=无法找到类型 ''{0}'' 的批注方法 ''{1}()'' # 0: type, 1: name, 2: message segment +# lint: classfile compiler.warn.annotation.method.not.found.reason=无法找到类型 ''{0}'' 的批注方法 ''{1}()'': {2} # 0: list of annotation, 1: symbol, 2: name, 3: message segment @@ -1681,6 +1781,7 @@ compiler.warn.unknown.enum.constant=未知的枚举常量 {1}.{2} compiler.warn.unknown.enum.constant.reason=未知的枚举常量 {1}.{2}\n原因: {3} # 0: type, 1: type +# lint: rawtypes compiler.warn.raw.class.use=找到原始类型: {0}\n缺少泛型类{1}的类型参数 compiler.warn.diamond.redundant.args=新表达式中存在冗余类型参数 (改用 diamond 运算符)。 @@ -1692,12 +1793,15 @@ compiler.warn.potential.lambda.found=可将此匿名内部类创建转换为 lam compiler.warn.method.redundant.typeargs=方法调用中存在冗余类型参数。 # 0: symbol, 1: message segment +# lint: varargs compiler.warn.varargs.redundant.trustme.anno=冗余的 {0} 批注。{1} # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.element=可串行化元素对成员 {0} 的访问可以由不受信任的代码公开执行 # 0: symbol +# lint: serial compiler.warn.access.to.member.from.serializable.lambda=可串行化 lambda 对成员 {0} 的访问可以由不受信任的代码公开执行 ##### @@ -1810,9 +1914,11 @@ compiler.misc.bad.enclosing.class={0}的封闭类错误: {1} compiler.misc.bad.enclosing.method=类 {0} 的封闭方法属性错误 # 0: file name +# lint: classfile compiler.warn.runtime.visible.invisible.param.annotations.mismatch={0} 中 RuntimeVisibleParameterAnnotations 属性和 RuntimeInvisibleParameterAnnotations 属性中的参数长度不匹配,将忽略这两个属性 # 0: file name +# lint: classfile compiler.warn.runtime.invisible.parameter.annotations={0} 中的 RuntimeVisibleParameterAnnotations 属性和 RuntimeInvisibleParameterAnnotations 属性无法映射到方法的参数 compiler.misc.bad.const.pool.tag=错误的常量池标记: {0} @@ -1904,6 +2010,7 @@ compiler.err.prob.found.req=不兼容的类型: {0} compiler.misc.prob.found.req=不兼容的类型: {0} # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.prob.found.req={0}\n需要: {2}\n找到: {1} # 0: type, 1: type @@ -1913,6 +2020,7 @@ compiler.misc.inconvertible.types={0}无法转换为{1} compiler.misc.possible.loss.of.precision=从{0}转换到{1}可能会有损失 # 0: type, 1: type +# lint: lossy-conversions compiler.warn.possible.loss.of.precision=在复合赋值中从 {0} 隐式转换为 {1} 可能会有损失 compiler.misc.unchecked.assign=未经检查的转换 @@ -2035,6 +2143,7 @@ compiler.misc.varargs.argument.mismatch=varargs 不匹配; {0} ##### # 0: symbol or type, 1: file name +# lint: auxiliaryclass compiler.warn.auxiliary.class.accessed.from.outside.of.its.source.file={1} 中的辅助类{0}不应从其自身的源文件以外访问 ## The first argument ({0}) is a "kindname". @@ -2174,12 +2283,15 @@ compiler.err.override.weaker.access={0}\n正在尝试分配更低的访问权限 compiler.err.override.incompatible.ret={0}\n返回类型{1}与{2}不兼容 # 0: message segment, 1: type, 2: type +# lint: unchecked compiler.warn.override.unchecked.ret={0}\n返回类型需要从{1}到{2}的未经检查的转换 # 0: message segment, 1: type +# lint: unchecked compiler.warn.override.unchecked.thrown={0}\n被覆盖的方法未抛出{1} # 0: symbol +# lint: overrides compiler.warn.override.equals.but.not.hashcode=类{0}覆盖了 equals, 但该类或任何超类都未覆盖 hashCode 方法 ## The following are all possible strings for the first argument ({0}) of the @@ -2245,12 +2357,15 @@ compiler.err.preview.feature.disabled.plural={0} 是预览功能,默认情况 compiler.err.preview.feature.disabled.classfile={0} 的类文件使用 Java SE {1} 的预览功能。\n(请使用 --enable-preview 以允许加载包含预览功能的类文件) # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use={0} 是预览功能,可能会在未来发行版中删除。 # 0: message segment (feature) +# lint: preview compiler.warn.preview.feature.use.plural={0} 是预览功能,可能会在未来发行版中删除。 # 0: file object (classfile), 1: string (expected version) +# lint: preview compiler.warn.preview.feature.use.classfile={0} 的类文件使用 Java SE {1} 的预览功能。 compiler.misc.feature.modules=模块 @@ -2515,6 +2630,7 @@ compiler.err.expected.module=预期 ''module'' compiler.err.module.not.found=找不到模块: {0} # 0: symbol +# lint: module compiler.warn.module.not.found=找不到模块: {0} # 0: name @@ -2584,6 +2700,7 @@ compiler.err.service.implementation.no.args.constructor.not.public=服务实现 compiler.err.package.empty.or.not.found=程序包为空或不存在: {0} # 0: symbol +# lint: opens compiler.warn.package.empty.or.not.found=程序包为空或不存在: {0} compiler.err.no.output.dir=未指定类输出目录 @@ -2644,6 +2761,7 @@ compiler.warn.bad.name.for.option={0} 选项的值中有错误的名称: ''{1}'' compiler.err.bad.name.for.option={0} 选项的值中有错误的名称: ''{1}'' # 0: option name, 1: symbol +# lint: options compiler.warn.module.for.option.not.found=找不到 {0} 选项中的模块名称: {1} compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATH 只能在编译未命名模块或在自动模块的上下文中编译时使用 @@ -2654,6 +2772,7 @@ compiler.err.add.exports.with.release=不允许在使用 --release 时从系统 # 0: symbol compiler.err.add.reads.with.release=不允许在使用 --release 时为系统模块 {0} 添加读取维边: +# lint: options compiler.warn.addopens.ignored=--add-opens 在编译时没有任何效果 compiler.misc.locn.module_source_path=模块源路径 @@ -2675,12 +2794,16 @@ compiler.err.invalid.module.specifier=不允许模块说明符: {0} compiler.warn.service.provided.but.not.exported.or.used=已提供服务接口, 但未导出或使用服务接口 # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible=模块 {2} 中的 {0} {1} 对需要该模块的客户机不可访问 # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported=未导出模块 {2} 中的 {0} {1} # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.not.required.transitive=未使用 ''requires transitive'' 间接导出模块 {2} 中的 {0} {1} # 0: kind name, 1: symbol, 2: symbol +# lint: exports compiler.warn.leaks.not.accessible.unexported.qualified=模块 {2} 中的 {0} {1} 可能对需要该模块的所有客户机都不可见 ### @@ -2712,7 +2835,10 @@ compiler.misc.is.a.type.variable=不得包含类型变量:{0} compiler.misc.is.duplicated=不得包含重复项:{0} # 0: type -compiler.misc.doesnt.extend.sealed=子类 {0} 必须扩展密封类 +compiler.misc.doesnt.extend.sealed=类 {0} 必须扩展密封类 + +# 0: kind name, 1: type +compiler.misc.doesnt.implement.sealed={0} {1} 必须扩展密封接口 compiler.misc.must.not.be.same.class=permits 子句中存在非法自引用 @@ -2912,9 +3038,14 @@ compiler.err.deconstruction.pattern.var.not.allowed=解构模式只能应用于 compiler.err.incorrect.number.of.nested.patterns=嵌套模式数不正确\n需要:{0}\n已找到:{1} # 0: kind name, 1: symbol +# lint: preview compiler.warn.declared.using.preview={0} {1} 是使用预览功能声明的,可能会在未来发行版中删除。 +# lint: identity compiler.warn.attempt.to.synchronize.on.instance.of.value.based.class=尝试在基于值的类的实例上同步 +# lint: identity +compiler.warn.attempt.to.use.value.based.where.identity.expected=使用基于值的类,其操作需要可靠的身份 + # 0: type compiler.err.enclosing.class.type.non.denotable=封闭类类型:{0}\n是不可指示的类型,尝试转换为可指示的类型 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties index 447695c9cf8..18a43abe14a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ javac.description=Java-Klasse und Schnittstellendefinitionen lesen und in Byteco javac.opt.g=Generiert alle Debugginginformationen javac.opt.g.none=Generiert keine Debugginginformationen javac.opt.g.lines.vars.source=Generiert nur einige Debugginginformationen -javac.opt.nowarn=Generiert keine Warnungen +javac.opt.nowarn=Nur obligatorische Warnungen generieren javac.opt.verbose=Gibt Nachrichten zu den Compilervorgängen aus javac.opt.deprecation=Gibt Quellspeicherorte aus, wo veraltete APIs verwendet werden javac.opt.classpath=Gibt an, wo sich die Benutzerklassendateien und Annotationsprozessoren befinden @@ -97,12 +97,12 @@ javac.opt.arg.pathname= javac.opt.arg.file= javac.opt.Xbootclasspath.p=Dem Bootstrap Classpath voranstellen javac.opt.Xbootclasspath.a=An Bootstrap Classpath anhängen -javac.opt.Xlint=Aktiviert die empfohlenen Warnungen -javac.opt.Xlint.all=Alle Warnungen aktivieren -javac.opt.Xlint.none=Alle Warnungen deaktivieren +javac.opt.Xlint=Empfohlene Warnungskategorien aktivieren +javac.opt.Xlint.all=Alle Warnungskategorien aktivieren +javac.opt.Xlint.none=Alle Warnungskategorien deaktivieren #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=Warnungen, die aktiviert oder deaktiviert werden sollen, durch Komma getrennt.\nStellen Sie einem Schlüssel "-" voran, um die angegebene Warnung zu deaktivieren.\nVerwenden Sie "--help-lint", um die unterstützten Schlüssel anzuzeigen. +javac.opt.Xlint.custom=Durch Komma getrennte Warnungskategorien, die aktiviert oder deaktiviert werden sollen.\nStellen Sie einem Schlüssel "-" voran, um die angegebene Warnung zu deaktivieren.\nVerwenden Sie "--help-lint", um die unterstützten Schlüssel anzuzeigen. javac.opt.Xlint.desc.auxiliaryclass=Warnt vor Auxiliary-Klassen, die in einer Quelldatei verborgen sind und aus anderen Dateien heraus verwendet werden. javac.opt.Xlint.desc.cast=Warnt vor unnötigen Umwandlungen mit Cast. @@ -159,7 +159,7 @@ javac.opt.Xlint.desc.serial=Warnt vor serialisierbaren Klassen, die kein serialV javac.opt.Xlint.desc.static=Warnt vor Zugriff auf ein statisches Mitglied mit einer Instanz. -javac.opt.Xlint.desc.strictfp=Warnt vor unnötiger Verwendung des strictfp-Modifizierers. +javac.opt.Xlint.desc.strictfp=Warnt vor unnötiger Verwendung des strictfp-Modifikators. javac.opt.Xlint.desc.text-blocks=Warnt vor inkonsistenten Leerzeichen in Textblockeinzug. @@ -175,7 +175,13 @@ javac.opt.Xlint.desc.preview=Warnt vor Verwendung von Vorschausprachfeatures. javac.opt.Xlint.desc.restricted=Warnt vor der Verwendung eingeschränkter Methoden. -javac.opt.Xlint.desc.synchronization=Warnt vor Synchronisierungsversuchen mit Instanzen wertbasierter Klassen. +javac.opt.Xlint.desc.synchronization=\ + Warnt vor Synchronisierungsversuchen mit Instanzen wertbasierter Klassen.\n\ +\ Dieser Schlüssel ist ein veralteter Alias für die Kategorie ''identity'', die dieselben Verwendungen und\n\ +\ Effekte hat. Benutzern wird empfohlen, die Kategorie ''identity'' für alle zukünftigen\n\ +\ und vorhandenen Verwendungen von ''synchronization'' zu verwenden. + +javac.opt.Xlint.desc.identity=Warnt vor Verwendungen wertbasierter Klassen, wenn eine Identitätsklasse erwartet wird. javac.opt.Xdoclint=Empfohlene Prüfungen für Probleme in javadoc-Kommentaren aktivieren # L10N: do not localize: all none diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties index c215ad5eeba..66e2e3dce39 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ javac.description=Javaクラスおよびインタフェースの定義を読み javac.opt.g=すべてのデバッグ情報を生成する javac.opt.g.none=デバッグ情報を生成しない javac.opt.g.lines.vars.source=いくつかのデバッグ情報のみを生成する -javac.opt.nowarn=警告を発生させない +javac.opt.nowarn=必須の警告のみを生成します javac.opt.verbose=コンパイラの動作についてメッセージを出力する javac.opt.deprecation=推奨されないAPIが使用されているソースの位置を出力する javac.opt.classpath=ユーザー・クラス・ファイルおよび注釈プロセッサを検索する位置を指定する @@ -97,12 +97,12 @@ javac.opt.arg.pathname= javac.opt.arg.file= javac.opt.Xbootclasspath.p=ブートストラップ・クラス・パスの先頭に付加する javac.opt.Xbootclasspath.a=ブートストラップ・クラス・パスに追加する -javac.opt.Xlint=推奨の警告を有効にする -javac.opt.Xlint.all=すべての警告を有効にします -javac.opt.Xlint.none=すべての警告を無効にします +javac.opt.Xlint=推奨の警告カテゴリを有効にします +javac.opt.Xlint.all=すべての警告カテゴリを有効にします +javac.opt.Xlint.none=すべての警告カテゴリを無効にします #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=有効または無効にする警告(カンマ区切り)。\n指定した警告を無効にするには、キーの前に''-''を指定します。\nサポートされているキーを表示するには--help-lintを使用します。 +javac.opt.Xlint.custom=有効または無効にする警告カテゴリ(カンマ区切り)。\n指定した警告を無効にするには、キーの前に''-''を指定します。\nサポートされているキーを表示するには--help-lintを使用します。 javac.opt.Xlint.desc.auxiliaryclass=ソース・ファイルで非表示になっているが他のファイルから使用されている補助クラスについて警告します。 javac.opt.Xlint.desc.cast=不要なキャストの使用について警告します。 @@ -175,7 +175,9 @@ javac.opt.Xlint.desc.preview=プレビュー言語機能の使用について警 javac.opt.Xlint.desc.restricted=制限されたメソッドの使用について警告します。 -javac.opt.Xlint.desc.synchronization=値ベース・クラスのインスタンスでの同期の試行について警告します。 +javac.opt.Xlint.desc.synchronization=値ベース・クラスのインスタンスでの同期の試行について警告します。\n このキーは、''identity''の非推奨のエイリアスであり、同じ使用方法と効果を\n 持ちます。ユーザーには、今後および既存の''synchronization''の使用に対して''identity''カテゴリを\n 使用することをお薦めします。 + +javac.opt.Xlint.desc.identity=アイデンティティ・クラスが必要な場所での値ベース・クラスの使用について警告します。 javac.opt.Xdoclint=javadocコメントの問題に関する推奨チェックを有効にします # L10N: do not localize: all none diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties index 1593280fd4d..efc6e73494e 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ javac.description=读取 Java 类和接口定义,并将其编译为字节码 javac.opt.g=生成所有调试信息 javac.opt.g.none=不生成任何调试信息 javac.opt.g.lines.vars.source=只生成某些调试信息 -javac.opt.nowarn=不生成任何警告 +javac.opt.nowarn=仅生成必需警告 javac.opt.verbose=输出有关编译器正在执行的操作的消息 javac.opt.deprecation=输出使用已过时的 API 的源位置 javac.opt.classpath=指定查找用户类文件和批注处理程序的位置 @@ -97,12 +97,12 @@ javac.opt.arg.pathname= javac.opt.arg.file= javac.opt.Xbootclasspath.p=置于引导类路径之前 javac.opt.Xbootclasspath.a=置于引导类路径之后 -javac.opt.Xlint=启用建议的警告 -javac.opt.Xlint.all=启用所有警告 -javac.opt.Xlint.none=禁用所有警告 +javac.opt.Xlint=启用建议的警告类别 +javac.opt.Xlint.all=启用所有警告类别 +javac.opt.Xlint.none=禁用所有警告类别 #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=要启用或禁用的警告(以逗号分隔)。\n在关键字前面加上 ''-'' 可禁用指定的警告。\n使用 --help-lint 可查看受支持的关键字。 +javac.opt.Xlint.custom=要启用或禁用的警告类别(以逗号分隔)。\n在关键字前面加上 ''-'' 可禁用指定的警告。\n使用 --help-lint 可查看受支持的关键字。 javac.opt.Xlint.desc.auxiliaryclass=有关辅助类在源文件中隐藏, 但在其他文件中使用的警告。 javac.opt.Xlint.desc.cast=有关使用了不必要转换的警告。 @@ -175,7 +175,9 @@ javac.opt.Xlint.desc.preview=有关使用预览语言功能的警告。 javac.opt.Xlint.desc.restricted=有关使用受限制方法的警告。 -javac.opt.Xlint.desc.synchronization=有关尝试在基于值的类的实例上同步的警告。 +javac.opt.Xlint.desc.synchronization=有关尝试在基于值的类的实例上同步的警告。\n 此密钥是 ''identity'' 的已过时别名,具有相同的用法和\n 效果。建议用户在 ''synchronization'' 的所有未来和现有\n 用法中使用 ''identity'' 类别。 + +javac.opt.Xlint.desc.identity=有关在需要身份类的情况下使用基于值的类的警告。 javac.opt.Xdoclint=为 javadoc 注释中的问题启用建议的检查 # L10N: do not localize: all none diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties index 0c67a60aa0a..7f12decb225 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -100,7 +100,10 @@ launcher.err.main.not.void=Methode "main" ist nicht mit Rückgabetyp "void" dekl launcher.err.cant.find.class=Klasse nicht gefunden: {0} # 0: string -launcher.err.cant.find.main.method=Methode "main(String[])" nicht gefunden in Klasse: {0} +launcher.err.cant.find.main.method=Konnte keine main(String[])- oder main()-Methode in der Klasse: {0} finden. + +# 0: string +launcher.err.cant.instantiate=Abstrakte Klasse: {0} kann nicht instanziiert werden # 0: string launcher.err.cant.access.main.method=kein Zugriff auf Methode "main" in Klasse: {0} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties index ef4d0f1f9e0..be1feb4a8a9 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -100,7 +100,10 @@ launcher.err.main.not.void=''main'メソッドが戻り型''void''で宣言さ launcher.err.cant.find.class=クラスが見つかりません: {0} # 0: string -launcher.err.cant.find.main.method=クラスにmain(String[])メソッドが見つかりません: {0} +launcher.err.cant.find.main.method=クラスにmain(String[])またはmain()メソッドが見つかりません: {0} + +# 0: string +launcher.err.cant.instantiate=抽象クラス: {0}はインスタンス化できません # 0: string launcher.err.cant.access.main.method=クラスのメイン・メソッドにアクセスできません: {0} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties index a442cfe1e68..5367036d82f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -100,7 +100,10 @@ launcher.err.main.not.void=未使用返回类型 ''void'' 声明 ''main'' 方法 launcher.err.cant.find.class=找不到类:{0} # 0: string -launcher.err.cant.find.main.method=在类 {0} 中找不到 main(String[]) 方法 +launcher.err.cant.find.main.method=在类 {0} 中找不到 main(String[]) 或 main() 方法 + +# 0: string +launcher.err.cant.instantiate=无法实例化抽象类 {0} # 0: string launcher.err.cant.access.main.method=无法访问类 {0} 中的 main 方法 diff --git a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties index 11c8b51dc53..f9eea0b9030 100644 --- a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties +++ b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2019, 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 diff --git a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_ja.properties b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_ja.properties index a92c8324681..765d60199cb 100644 --- a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_ja.properties +++ b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2019, 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 diff --git a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_zh_CN.properties b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_zh_CN.properties index 994efca2408..246381ed212 100644 --- a/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_zh_CN.properties +++ b/src/jdk.compiler/share/classes/sun/tools/serialver/resources/serialver_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2019, 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 diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties index fe4ff9b50c4..c5d9f41ee85 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties @@ -25,7 +25,7 @@ # shared (from jarsigner) SPACE=\u0020 -6SPACE=\u0020 \u0020 +6SPACE=\ \u0020 COMMA=,\u0020 provclass.not.a.provider=%s kein Provider provider.name.not.found=Provider namens "%s" nicht gefunden @@ -37,8 +37,8 @@ Illegal.option.=Unzulässige Option:\u0020 If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified=Wenn -protected angegeben ist, dürfen -storepass und -keypass nicht angegeben werden If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified=Wenn der Keystore nicht kennwortgeschützt ist, dürfen -storepass und -keypass nicht angegeben werden Usage.jarsigner.options.jar.file.alias=Verwendung: jarsigner [options] jar-file alias -.jarsigner.verify.options.jar.file.alias.=\u0020 jarsigner -verify [options] jar-file [alias...] -.jarsigner.version=\u0020 jarsigner -version +.jarsigner.verify.options.jar.file.alias.=\ jarsigner -verify [options] jar-file [alias...] +.jarsigner.version=\ jarsigner -version .keystore.url.keystore.location=[-keystore ] Keystore-Speicherort .storepass.password.password.for.keystore.integrity=[-storepass ] Kennwort für Keystore-Integrität .storetype.type.keystore.type=[-storetype ] Keystore-Typ @@ -51,7 +51,7 @@ Usage.jarsigner.options.jar.file.alias=Verwendung: jarsigner [options] jar-file .verify.verify.a.signed.JAR.file=[-verify] Verifiziert eine signierte JAR-Datei .version.print.the.program.version=[-version] Gibt die Programmversion aus .verbose.suboptions.verbose.output.when.signing.verifying.=[-verbose[:suboptions]] Verbose-Ausgabe beim Signieren/Verifizieren. -.suboptions.can.be.all.grouped.or.summary=\u0020 Als Unteroptionen sind "all", "grouped" und "summary" möglich +.suboptions.can.be.all.grouped.or.summary=\ Als Unteroptionen sind "all", "grouped" und "summary" möglich .certs.display.certificates.when.verbose.and.verifying=[-certs] Zeigt Zertifikate bei Verbose und Verifizierung an .certs.revocation.check=[-revCheck] Aktiviert die Zertifikatswiderrufprüfung .tsa.url.location.of.the.Timestamping.Authority=[-tsa ] Ort der Zeitstempelautorität @@ -63,9 +63,9 @@ Usage.jarsigner.options.jar.file.alias=Verwendung: jarsigner [options] jar-file .protected.keystore.has.protected.authentication.path=[-protected] Keystore hat geschützten Authentifizierungspfad .providerName.name.provider.name=[-providerName ] Providername .add.provider.option=[-addprovider Fügt einen Sicherheitsprovider nach Name hinzu (z.B. SunPKCS11) -.providerArg.option.1=\u0020 [-providerArg ]] ... Konfiguriert Argument für -addprovider +.providerArg.option.1=\ [-providerArg ]] ... Konfiguriert Argument für -addprovider .providerClass.option=[-providerClass Fügt einen Sicherheitsprovider nach vollqualifiziertem Klassennamen hinzu -.providerArg.option.2=\u0020 [-providerArg ]] ... Konfiguriert Argument für -providerClass +.providerArg.option.2=\ [-providerArg ]] ... Konfiguriert Argument für -providerClass .providerPath.option=[-providerPath ] Provider-Classpath .strict.treat.warnings.as.errors=[-strict] Behandelt Warnungen als Fehler .conf.url.specify.a.pre.configured.options.file=[-conf ] Vorkonfigurierte Optionsdatei angeben @@ -83,11 +83,11 @@ k=k X=X q=? .and.d.more.=(und %d mehr) -.s.signature.was.verified.=\u0020 s = Signatur wurde verifiziert\u0020 -.m.entry.is.listed.in.manifest=\u0020 m = Eintrag ist in Manifest aufgeführt -.k.at.least.one.certificate.was.found.in.keystore=\u0020 k = Mindestens ein Zertifikat im Keystore gefunden -.X.not.signed.by.specified.alias.es.=\u0020 X = Nicht von den angegebenen Aliasnamen signiert -.q.unsigned.entry=\u0020 ? = Nicht signierter Eintrag +.s.signature.was.verified.=\ s = Signatur wurde verifiziert\u0020 +.m.entry.is.listed.in.manifest=\ m = Eintrag ist in Manifest aufgeführt +.k.at.least.one.certificate.was.found.in.keystore=\ k = Mindestens ein Zertifikat im Keystore gefunden +.X.not.signed.by.specified.alias.es.=\ X = Nicht von den angegebenen Aliasnamen signiert +.q.unsigned.entry=\ ? = Nicht signierter Eintrag no.manifest.=Kein Manifest. .Signature.related.entries.=(Signaturbezogene Einträge) .Unsigned.entries.=(Nicht signierte Einträge) @@ -96,14 +96,15 @@ jar.is.unsigned=JAR-Datei ist nicht signiert. jar.treated.unsigned=Warnung: Signatur kann entweder nicht geparst oder nicht verifiziert werden. Die JAR-Datei wird als nicht signiert behandelt. Weitere Informationen erhalten Sie, indem Sie "jarsigner" mit aktiviertem Debugging erneut ausführen (-J-Djava.security.debug=jar). jar.treated.unsigned.see.weak=Die JAR-Datei wird als nicht signiert behandelt, da sie mit einem schwachen Algorithmus signiert wurde, der jetzt deaktiviert ist.\n\nFühren Sie "jarsigner" mit der Option "-verbose" erneut aus, um weitere Einzelheiten zu erhalten. jar.treated.unsigned.see.weak.verbose=Warnung: Die JAR-Datei wird als nicht signiert behandelt, da sie mit einem schwachen Algorithmus signiert wurde, der mittlerweile von der folgenden Sicherheitseigenschaft deaktiviert wurde: -jar.signed.=JAR-Datei signiert. +multiple.manifest.warning.=Doppelte Manifesteinträge in der JAR-Datei erkannt. JarSigner hat nur einen Eintrag bearbeitet. Die anderen wurden verworfen. +jar.signed.=JAR signiert. jar.signed.with.signer.errors.=JAR-Datei signiert, mit Signaturgeberfehlern. -jar.verified.=JAR-Datei verifiziert. +jar.verified.=JAR verifiziert. jar.verified.with.signer.errors.=JAR-Datei verifiziert, mit Signaturgeberfehlern. history.with.ts=- Von "%1$s" signiert\n Digestalgorithmus: %2$s\n Signaturalgorithmus: %3$s, %4$s\n Zeitstempel von "%6$s" am %5$tc\n Digestalgorithmus für Zeitstempel: %7$s\n Signaturalgorithmus für Zeitstempel: %8$s, %9$s history.without.ts=- Von "%1$s" signiert\n Digestalgorithmus: %2$s\n Signaturalgorithmus: %3$s, %4$s -history.nonexistent.entries=\u0020 Warnung: Nicht vorhandene signierte Einträge:\u0020 +history.nonexistent.entries=\ Warnung: Nicht vorhandene signierte Einträge:\u0020 history.unparsable=- Signaturbezogene Datei %s kann nicht geparst werden history.nosf=- Signaturbezogene Datei META-INF/%s.SF fehlt history.nobk=- Blockdatei für signaturbezogene Datei META-INF/%s.SF fehlt @@ -113,8 +114,8 @@ with.algparams.weak=%1$s mit %2$s (schwach) with.disabled=%s (deaktiviert) with.algparams.disabled=%1$s mit %2$s (deaktiviert) key.bit=%s-Schlüssel -key.bit.weak=%s Schlüssel (schwach) -key.bit.disabled=%s Schlüssel (deaktiviert) +key.bit.weak=%s-Schlüssel (schwach) +key.bit.disabled=%s-Schlüssel (deaktiviert) nonexistent.entries.found=Diese JAR-Datei enthält signierte Einträge für Dateien, die nicht vorhanden sind. Weitere Details finden Sie in der Verbose-Ausgabe (-verbose). external.file.attributes.detected=POSIX-Dateiberechtigung und/oder Symlink-Attribute erkannt. Diese Attribute werden bei der Signatur ignoriert und sind nicht durch die Signatur geschützt. @@ -122,9 +123,9 @@ jarsigner.=jarsigner:\u0020 signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.=Signaturdateiname muss aus den folgenden Zeichen bestehen: A-Z, 0-9, _ oder - unable.to.open.jar.file.=JAR-Datei kann nicht geöffnet werden:\u0020 unable.to.create.=Erstellen nicht möglich:\u0020 -.adding.=\u0020 Wird hinzugefügt:\u0020 -.updating.=\u0020Wird aktualisiert:\u0020 -.signing.=\u0020 Wird signiert:\u0020 +.adding.=\ Wird hinzugefügt:\u0020 +.updating.=\ Wird aktualisiert:\u0020 +.signing.=\ Wird signiert:\u0020 attempt.to.rename.signedJarFile.to.jarFile.failed=Der Versuch, {0} in {1} umzubenennen, war nicht erfolgreich attempt.to.rename.jarFile.to.origJar.failed=Der Versuch, {0} in {1} umzubenennen, war nicht erfolgreich unable.to.sign.jar.=JAR-Datei kann nicht signiert werden:\u0020 @@ -149,7 +150,7 @@ certificate.will.expire.on=Zertifikat läuft am {0} ab .Invalid.certificate.chain.=[Ungültige Zertifikatskette:\u0020 .Invalid.TSA.certificate.chain.=[Ungültige TSA-Zertifikatskette:\u0020 requesting.a.signature.timestamp=Signaturzeitstempel wird angefordert -TSA.location.=TSA-Ort:\u0020 +TSA.location.=TSA-Speicherort:\u0020 TSA.certificate.=TSA-Zertifikat:\u0020 no.response.from.the.Timestamping.Authority.=Keine Antwort von der Zeitstempelautorität. Bei Verbindungen hinter einer Firewall muss möglicherweise ein HTTP- oder HTTPS-Proxy angegeben werden. Geben Sie die folgenden Optionen für "jarsigner" an: or=oder @@ -159,9 +160,9 @@ Warning.=Warnung:\u0020 Error.=Fehler:\u0020 ...Signer=>>> Signaturgeber ...TSA=>>> TSA -trusted.certificate=vertrauenswürdiges Zertifikat +trusted.certificate=Vertrauenswürdiges Zertifikat This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.=Diese JAR-Datei enthält nicht signierte Einträge, deren Integrität nicht geprüft wurde.\u0020 -This.jar.contains.entries.whose.signer.certificate.has.expired.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat abgelaufen ist. +This.jar.contains.entries.whose.signer.certificate.has.expired.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat abgelaufen ist.\u0020 This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat innerhalb der nächsten sechs Monate abläuft.\u0020 This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat noch nicht gültig ist.\u0020 This.jar.contains.entries.whose.signer.certificate.is.self.signed.=Diese JAR-Datei enthält Einträge, deren Signaturgeberzertifikat selbstsigniert ist. @@ -188,9 +189,9 @@ The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.and.is. The.timestamp.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=Der %1$s-Digestalgorithmus des Zeitstempels gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zukünftigen Update deaktiviert. The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=Der %1$s-Digestalgorithmus gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zukünftigen Update deaktiviert. The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=Der %1$s-Signaturalgorithmus gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zukünftigen Update deaktiviert. -size.bit.alg=%1$d-Bit %2$s -The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=Der %s Signaturschlüssel wird als Sicherheitsrisiko betrachtet. Wird in einem zukünftigen Update deaktiviert. -The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=Der %s Signaturschlüssel wird als Sicherheitsrisiko betrachtet und ist deaktiviert. +size.bit.alg=%1$d-Bit-%2$s +The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=Der %1$s-Signaturschlüssel gilt als Sicherheitsrisiko. Er wird in einem zukünftigen Update deaktiviert. +The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=Der %s-Signaturschlüssel gilt als Sicherheitsrisiko und ist deaktiviert. This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1=Diese JAR-Datei enthält Einträge, deren Zertifikatskette ungültig ist. Grund: %s This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1=Diese JAR-Datei enthält Einträge, deren TSA-Zertifikatskette ungültig ist. Grund: %s no.timestamp.signing=Weder -tsa noch -tsacert wurde angegeben, und diese JAR-Datei hat keinen Zeitstempel. Ohne Zeitstempel können Benutzer diese JAR-Datei nach dem Ablaufdatum des Signaturgeberzertifikats (%1$tY-%1$tm-%1$td) möglicherweise nicht mehr validieren. @@ -205,3 +206,17 @@ Cannot.find.environment.variable.=Umgebungsvariable kann nicht gefunden werden:\ Cannot.find.file.=Datei kann nicht gefunden werden:\u0020 event.ocsp.check=Verbindung zu OCSP-Server bei %s wird hergestellt... event.crl.check=CRL wird von %s heruntergeladen... +manifest.missing.when.reading.jarfile=Manifest fehlt beim Lesen über JarFile +manifest.missing.when.reading.jarinputstream=Manifest fehlt beim Lesen über JarInputStream +manifest.attribute.1.present.when.reading.jarfile.but.missing.via.jarinputstream=Manifesthauptattribut %s ist beim Lesen über JarFile vorhanden, aber fehlt beim Lesen über JarInputStream +manifest.attribute.1.present.when.reading.jarinputstream.but.missing.via.jarfile=Manifesthauptattribut %s ist beim Lesen über JarInputStream vorhanden, aber fehlt beim Lesen über JarFile +manifest.attribute.1.differs.jarfile.value.2.jarinputstream.value.3=Manifesthauptattribut %1$s unterschiedlich: JarFile-Wert = %2$s, JarInputStream-Wert = %3$s +entry.1.present.when.reading.jarinputstream.but.missing.via.jarfile=Eintrag %s ist beim Lesen über JarInputStream vorhanden, aber fehlt beim Lesen über JarFile +entry.1.present.when.reading.jarfile.but.missing.via.jarinputstream=Eintrag %s ist beim Lesen über JarFile vorhanden, aber fehlt beim Lesen über JarInputStream +entry.1.present.in.jarfile.but.unreadable=Eintrag %s ist in JarFile vorhanden, aber nicht lesbar +codesigners.different.for.entry.1.when.reading.jarfile.and.jarinputstream=Codesignaturgeber für Eintrag %s beim Lesen über JarFile anders als bei JarInputStream +entry.1.is.signed.in.jarfile.but.is.not.signed.in.jarinputstream=Eintrag %s ist in JarFile, aber nicht in JarInputStream signiert +entry.1.is.signed.in.jarinputstream.but.is.not.signed.in.jarfile=Eintrag %s ist in JarInputStream, aber nicht in JarFile signiert +jar.contains.internal.inconsistencies.result.in.different.contents.via.jarfile.and.jarinputstream=Diese JAR-Datei enthält interne Inkonsistenzen, die zu anderem Inhalt beim Lesen über JarFile als beim Lesen über JarInputStream führen können: +signature.verification.failed.on.entry.1.when.reading.via.jarinputstream=Signaturverifizierung war für Eintrag %s beim Lesen über JarInputStream nicht erfolgreich +signature.verification.failed.on.entry.1.when.reading.via.jarfile=Signaturverifizierung war für Eintrag %s beim Lesen über JarFile nicht erfolgreich diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties index e13d8b5a471..97ab6a918cb 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties @@ -25,7 +25,7 @@ # shared (from jarsigner) SPACE=\u0020 -6SPACE=\u0020 \u0020 +6SPACE=\ \u0020 COMMA=,\u0020 provclass.not.a.provider=%sはプロバイダではありません provider.name.not.found=プロバイダ名"%s"が見つかりません @@ -37,8 +37,8 @@ Illegal.option.=不正なオプション:\u0020 If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified=-protectedを指定する場合は、-storepassおよび-keypassを指定しないでください If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified=キーストアがパスワードで保護されていない場合、-storepassおよび-keypassを指定しないでください Usage.jarsigner.options.jar.file.alias=使用方法: jarsigner [options] jar-file alias -.jarsigner.verify.options.jar.file.alias.=\u0020 jarsigner -verify [options] jar-file [alias...] -.jarsigner.version=\u0020 jarsigner -version +.jarsigner.verify.options.jar.file.alias.=\ jarsigner -verify [options] jar-file [alias...] +.jarsigner.version=\ jarsigner -version .keystore.url.keystore.location=[-keystore ] キーストアの位置 .storepass.password.password.for.keystore.integrity=[-storepass ] キーストア整合性のためのパスワード .storetype.type.keystore.type=[-storetype ] キーストアの型 @@ -47,25 +47,25 @@ Usage.jarsigner.options.jar.file.alias=使用方法: jarsigner [options] jar-fil .sigfile.file.name.of.SF.DSA.file=[-sigfile ] .SF/.DSAファイルの名前 .signedjar.file.name.of.signed.JAR.file=[-signedjar ] 署名付きJARファイルの名前 .digestalg.algorithm.name.of.digest.algorithm=[-digestalg ] ダイジェスト・アルゴリズムの名前 -.sigalg.algorithm.name.of.signature.algorithm=[-sigalg ] シグネチャ・アルゴリズムの名前 +.sigalg.algorithm.name.of.signature.algorithm=[-sigalg ] 署名アルゴリズムの名前 .verify.verify.a.signed.JAR.file=[-verify] 署名付きJARファイルの検証 .version.print.the.program.version=[-version] プログラム・バージョンを出力します .verbose.suboptions.verbose.output.when.signing.verifying.=[-verbose[:suboptions]] 署名/検証時の詳細出力。 -.suboptions.can.be.all.grouped.or.summary=\u0020 サブオプションとして、all、groupedまたはsummaryを使用できます +.suboptions.can.be.all.grouped.or.summary=\ サブオプションとして、all、groupedまたはsummaryを使用できます .certs.display.certificates.when.verbose.and.verifying=[-certs] 詳細出力および検証時に証明書を表示 .certs.revocation.check=[-revCheck] 証明書失効チェックの有効化 .tsa.url.location.of.the.Timestamping.Authority=[-tsa ] タイムスタンプ局の場所 .tsacert.alias.public.key.certificate.for.Timestamping.Authority=[-tsacert ] タイムスタンプ局の公開キー証明書 .tsapolicyid.tsapolicyid.for.Timestamping.Authority=[-tsapolicyid ] タイムスタンプ局のTSAPolicyID .tsadigestalg.algorithm.of.digest.data.in.timestamping.request=[-tsadigestalg ] タイムスタンプ・リクエストのダイジェスト・データのアルゴリズム -.internalsf.include.the.SF.file.inside.the.signature.block=[-internalsf] シグネチャ・ブロックに.SFファイルを含める +.internalsf.include.the.SF.file.inside.the.signature.block=[-internalsf] 署名ブロックに.SFファイルを含める .sectionsonly.don.t.compute.hash.of.entire.manifest=[-sectionsonly] マニフェスト全体のハッシュは計算しない .protected.keystore.has.protected.authentication.path=[-protected] キーストアには保護された認証パスがある .providerName.name.provider.name=[-providerName ] プロバイダ名 .add.provider.option=[-addprovider 名前でセキュリティ・プロバイダを追加する(SunPKCS11など) -.providerArg.option.1=\u0020 [-providerArg ]] ... -addproviderの引数を構成する +.providerArg.option.1=\ [-providerArg ]] ... -addproviderの引数を構成する .providerClass.option=[-providerClass 完全修飾クラス名でセキュリティ・プロバイダを追加する -.providerArg.option.2=\u0020 [-providerArg ]] ... -providerClassの引数を構成する +.providerArg.option.2=\ [-providerArg ]] ... -providerClassの引数を構成する .providerPath.option=[-providerPath ] プロバイダ・クラスパス .strict.treat.warnings.as.errors=[-strict] 警告をエラーとして処理 .conf.url.specify.a.pre.configured.options.file=[-conf ] 事前構成済のオプション・ファイルを指定する @@ -83,19 +83,20 @@ k=k X=X q=? .and.d.more.=(他にも%d個) -.s.signature.was.verified.=\u0020 s=シグネチャが検証されました\u0020 -.m.entry.is.listed.in.manifest=\u0020 m=エントリがマニフェスト内にリストされます -.k.at.least.one.certificate.was.found.in.keystore=\u0020 k=1つ以上の証明書がキーストアで検出されました -.X.not.signed.by.specified.alias.es.=\u0020 X =指定した別名で署名されていません -.q.unsigned.entry=\u0020 ? = 署名なしのエントリ +.s.signature.was.verified.=\ s=署名が検証されました\u0020 +.m.entry.is.listed.in.manifest=\ m=エントリがマニフェスト内にリストされます +.k.at.least.one.certificate.was.found.in.keystore=\ k=1つ以上の証明書がキーストアで検出されました +.X.not.signed.by.specified.alias.es.=\ X =指定した別名で署名されていません +.q.unsigned.entry=\ ? = 署名なしのエントリ no.manifest.=マニフェストは存在しません。 -.Signature.related.entries.=(シグネチャ関連エントリ) +.Signature.related.entries.=(署名関連エントリ) .Unsigned.entries.=(署名なしのエントリ) .Directory.entries.=(ディレクトリ・エントリ) jar.is.unsigned=jarは署名されていません。 jar.treated.unsigned=警告: 署名が構文解析できないか検証できないため、このjarは署名なしとして扱われます。詳細は、デバッグを有効にして(-J-Djava.security.debug=jar) jarsignerを再実行してください。 jar.treated.unsigned.see.weak=このjarは、現在無効になっている弱いアルゴリズムで署名されているため、署名なしとして扱われます。\n\n詳細は、-verboseオプションを使用してjarsignerを再実行してください。 jar.treated.unsigned.see.weak.verbose=警告: このjarは、セキュリティ・プロパティによって現在無効になっている弱いアルゴリズムで署名されているため、署名なしとして扱われます: +multiple.manifest.warning.=jarファイルで重複したマニフェスト・エントリが検出されました。JarSignerは1つでのみ動作し、その他は破棄されました。 jar.signed.=jarは署名されました。 jar.signed.with.signer.errors.=jarは署名されました - 署名者エラーがあります。 jar.verified.=jarが検証されました。 @@ -103,7 +104,7 @@ jar.verified.with.signer.errors.=jarは検証されました - 署名者エラ history.with.ts=- 署名者: "%1$s"\n ダイジェスト・アルゴリズム: %2$s\n 署名アルゴリズム: %3$s、%4$s\n タイムスタンプ付加者: "%6$s" 日時: %5$tc\n タイムスタンプのダイジェスト・アルゴリズム: %7$s\n タイムスタンプの署名アルゴリズム: %8$s、%9$s history.without.ts=- 署名者: "%1$s"\n ダイジェスト・アルゴリズム: %2$s\n 署名アルゴリズム: %3$s、%4$s -history.nonexistent.entries=\u0020 警告: 存在しない署名済エントリ:\u0020 +history.nonexistent.entries=\ 警告: 存在しない署名済エントリ:\u0020 history.unparsable=- 署名関連ファイル%sを解析できません history.nosf=- 署名関連ファイルMETA-INF/%s.SFがありません history.nobk=- 署名関連ファイルMETA-INF/%s.SFのブロック・ファイルがありません @@ -113,18 +114,18 @@ with.algparams.weak=%2$sを使用した%1$s (弱) with.disabled=%s (無効) with.algparams.disabled=%2$sを使用した%1$s (無効) key.bit=%sキー -key.bit.weak=%sキー(弱い) +key.bit.weak=%sキー(弱) key.bit.disabled=%sキー(無効) nonexistent.entries.found=このjarには、存在しないファイルの署名済エントリが含まれます。詳細は、-verbose出力を参照してください。 external.file.attributes.detected=POSIXファイル権限またはsymlink(あるいはその両方)の属性が検出されました。署名中はこれらの属性は無視され、署名によって保護されません。 jarsigner.=jarsigner:\u0020 -signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.=シグネチャのファイル名に使用できる文字は、A-Z、0-9、_、- のみです。 +signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.=署名のファイル名に使用できる文字は、A-Z、0-9、_、- のみです unable.to.open.jar.file.=次のjarファイルを開くことができません:\u0020 unable.to.create.=作成できません:\u0020 -.adding.=\u0020 追加中:\u0020 -.updating.=\u0020更新中:\u0020 -.signing.=\u0020 署名中:\u0020 +.adding.=\ 追加中:\u0020 +.updating.=\ 更新中:\u0020 +.signing.=\ 署名中:\u0020 attempt.to.rename.signedJarFile.to.jarFile.failed={0}の名前を{1}に変更しようとしましたが失敗しました attempt.to.rename.jarFile.to.origJar.failed={0}の名前を{1}に変更しようとしましたが失敗しました unable.to.sign.jar.=jarに署名できません:\u0020 @@ -148,7 +149,7 @@ certificate.is.not.valid.until=証明書は{0}まで有効ではありません certificate.will.expire.on=証明書は{0}に失効します .Invalid.certificate.chain.=[無効な証明書チェーン:\u0020 .Invalid.TSA.certificate.chain.=[無効なTSA証明書チェーン:\u0020 -requesting.a.signature.timestamp=シグネチャ・タイムスタンプのリクエスト +requesting.a.signature.timestamp=署名タイムスタンプのリクエスト TSA.location.=TSAの場所:\u0020 TSA.certificate.=TSA証明書:\u0020 no.response.from.the.Timestamping.Authority.=タイムスタンプ局からのレスポンスがありません。ファイアウォールを介して接続するときは、必要に応じてHTTPまたはHTTPSプロキシを指定してください。jarsignerに次のオプションを指定してください: @@ -164,7 +165,7 @@ This.jar.contains.unsigned.entries.which.have.not.been.integrity.checked.=この This.jar.contains.entries.whose.signer.certificate.has.expired.=このjarには、署名者の証明書が期限切れのエントリが含まれています。\u0020 This.jar.contains.entries.whose.signer.certificate.will.expire.within.six.months.=このjarには、署名者の証明書が6か月以内に期限切れとなるエントリが含まれています。\u0020 This.jar.contains.entries.whose.signer.certificate.is.not.yet.valid.=このjarには、署名者の証明書がまだ有効になっていないエントリが含まれています。\u0020 -This.jar.contains.entries.whose.signer.certificate.is.self.signed.=このjarには、署名者の証明書が自己署名されているエントリが含まれています。\u0020 +This.jar.contains.entries.whose.signer.certificate.is.self.signed.=このjarには、署名者の証明書が自己署名されているエントリが含まれています。 Re.run.with.the.verbose.and.certs.options.for.more.details.=詳細は、-verboseおよび-certsオプションを使用して再実行してください。 The.signer.certificate.has.expired.=署名者の証明書は期限切れです。 The.timestamp.expired.1.but.usable.2=タイムスタンプは%1$tY-%1$tm-%1$tdに期限切れになります。ただし、JARは署名者の証明書が%2$tY-%2$tm-%2$tdに期限切れになるまで有効です。 @@ -188,9 +189,9 @@ The.1.algorithm.specified.for.the.2.option.is.considered.a.security.risk.and.is. The.timestamp.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$sタイムスタンプ・ダイジェスト・アルゴリズムは、セキュリティ・リスクとみなされます。このアルゴリズムは将来の更新で無効化されます。 The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$sダイジェスト・アルゴリズムは、セキュリティ・リスクとみなされます。このアルゴリズムは将来の更新で無効化されます。 The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$s署名アルゴリズムは、セキュリティ・リスクとみなされます。このアルゴリズムは将来の更新で無効化されます。 -size.bit.alg=%1$dビット%2$s -The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=%s署名キーはセキュリティ・リスクとみなされます。今後の更新では無効になります。 -The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=%s署名キーはセキュリティ・リスクとみなされ、無効になっています。 +size.bit.alg=%1$d-ビット %2$s +The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=%s署名キーはセキュリティ・リスクとみなされます。これは将来の更新で無効化されます。 +The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=%s署名キーはセキュリティ・リスクとみなされ、無効化されています。 This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1=このjarには、証明書チェーンが無効なエントリが含まれています。理由: %s This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1=このjarには、TSA証明書チェーンが無効なエントリが含まれています。理由: %s no.timestamp.signing=-tsaまたは-tsacertが指定されていないため、このjarにはタイムスタンプが付加されていません。タイムスタンプがないと、署名者証明書の有効期限(%1$tY-%1$tm-%1$td)後に、ユーザーはこのjarを検証できない可能性があります。 @@ -205,3 +206,17 @@ Cannot.find.environment.variable.=環境変数が見つかりません:\u0020 Cannot.find.file.=ファイルが見つかりません:\u0020 event.ocsp.check=%sのOCSPサーバーに接続しています... event.crl.check=%sからCRLをダウンロードしています... +manifest.missing.when.reading.jarfile=JarFileを介して読み取るときにマニフェストがありません +manifest.missing.when.reading.jarinputstream=JarInputStreamを介して読み取るときにマニフェストがありません +manifest.attribute.1.present.when.reading.jarfile.but.missing.via.jarinputstream=マニフェストのメイン属性%sは、JarFileを介して読み取るときは存在しますが、JarInputStreamを介して読み取るときにはありません +manifest.attribute.1.present.when.reading.jarinputstream.but.missing.via.jarfile=マニフェストのメイン属性%sは、JarInputStreamを介して読み取るときは存在しますが、JarFileを介して読み取るときにはありません +manifest.attribute.1.differs.jarfile.value.2.jarinputstream.value.3=マニフェストのメイン属性%1$sが異なります: JarFileの値 = %2$s、JarInputStreamの値 = %3$s +entry.1.present.when.reading.jarinputstream.but.missing.via.jarfile=エントリ%sは、JarInputStreamを介して読み取るときは存在しますが、JarFileを介して読み取るときにはありません +entry.1.present.when.reading.jarfile.but.missing.via.jarinputstream=エントリ%sは、JarFileを介して読み取るときは存在しますが、JarInputStreamを介して読み取るときにはありません +entry.1.present.in.jarfile.but.unreadable=エントリ%sはJarFileに存在しますが読み取れません +codesigners.different.for.entry.1.when.reading.jarfile.and.jarinputstream=JarFileとJarInputStreamから読み取る場合のエントリ%sのコード署名者が異なります +entry.1.is.signed.in.jarfile.but.is.not.signed.in.jarinputstream=エントリ%sは、JarFileでは署名されていますが、JarInputStreamでは署名されていません +entry.1.is.signed.in.jarinputstream.but.is.not.signed.in.jarfile=エントリ%sは、JarInputStreamでは署名されていますが、JarFileでは署名されていません +jar.contains.internal.inconsistencies.result.in.different.contents.via.jarfile.and.jarinputstream=このJARファイルには内部的な不整合があるため、JarFileとJarInputStreamから読み取る場合にコンテンツが異なる可能性があります: +signature.verification.failed.on.entry.1.when.reading.via.jarinputstream=JarInputStreamを介して読み取るときに署名検証がエントリ%sで失敗しました +signature.verification.failed.on.entry.1.when.reading.via.jarfile=JarFileを介して読み取るときに署名検証がエントリ%sで失敗しました diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties index 2558239039f..378cc3ba9fc 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties @@ -25,7 +25,7 @@ # shared (from jarsigner) SPACE=\u0020 -6SPACE=\u0020 \u0020 +6SPACE=\ \u0020 COMMA=,\u0020 provclass.not.a.provider=%s不是提供方 provider.name.not.found=未找到名为 "%s" 的提供方 @@ -37,8 +37,8 @@ Illegal.option.=非法选项:\u0020 If.protected.is.specified.then.storepass.and.keypass.must.not.be.specified=如果指定了 -protected, 则不能指定 -storepass 和 -keypass If.keystore.is.not.password.protected.then.storepass.and.keypass.must.not.be.specified=如果密钥库未受口令保护, 则不能指定 -storepass 和 -keypass Usage.jarsigner.options.jar.file.alias=用法: jarsigner [选项] jar-file 别名 -.jarsigner.verify.options.jar.file.alias.=\u0020 jarsigner -verify [选项] jar-file [别名...] -.jarsigner.version=\u0020 jarsigner -version +.jarsigner.verify.options.jar.file.alias.=\ jarsigner -verify [选项] jar-file [别名...] +.jarsigner.version=\ jarsigner -version .keystore.url.keystore.location=[-keystore ] 密钥库位置 .storepass.password.password.for.keystore.integrity=[-storepass <口令>] 用于密钥库完整性的口令 .storetype.type.keystore.type=[-storetype <类型>] 密钥库类型 @@ -51,7 +51,7 @@ Usage.jarsigner.options.jar.file.alias=用法: jarsigner [选项] jar-file 别 .verify.verify.a.signed.JAR.file=[-verify] 验证已签名的 JAR 文件 .version.print.the.program.version=[-version] 输出程序版本 .verbose.suboptions.verbose.output.when.signing.verifying.=[-verbose[:suboptions]] 签名/验证时输出详细信息。 -.suboptions.can.be.all.grouped.or.summary=\u0020 子选项可以是 all, grouped 或 summary +.suboptions.can.be.all.grouped.or.summary=\ 子选项可以是 all, grouped 或 summary .certs.display.certificates.when.verbose.and.verifying=[-certs] 输出详细信息和验证时显示证书 .certs.revocation.check=[-revCheck] 启用证书撤消检查 .tsa.url.location.of.the.Timestamping.Authority=[-tsa ] 时间戳颁发机构的位置 @@ -63,9 +63,9 @@ Usage.jarsigner.options.jar.file.alias=用法: jarsigner [选项] jar-file 别 .protected.keystore.has.protected.authentication.path=[-protected] 密钥库具有受保护验证路径 .providerName.name.provider.name=[-providerName <名称>] 提供方名称 .add.provider.option=[-addprovider <名称> 按名称 (例如 SunPKCS11) 添加安全提供方 -.providerArg.option.1=\u0020 [-providerArg <参数>]] ... 配置 -addprovider 的参数 +.providerArg.option.1=\ [-providerArg <参数>]] ... 配置 -addprovider 的参数 .providerClass.option=[-providerClass <类> 按全限定类名添加安全提供方 -.providerArg.option.2=\u0020 [-providerArg <参数>]] ... 配置 -providerClass 的参数 +.providerArg.option.2=\ [-providerArg <参数>]] ... 配置 -providerClass 的参数 .providerPath.option=[-providerPath ] 提供方类路径 .strict.treat.warnings.as.errors=[-strict] 将警告视为错误 .conf.url.specify.a.pre.configured.options.file=[-conf ] 指定预配置的选项文件 @@ -83,11 +83,11 @@ k=k X=X q=? .and.d.more.=(%d 及以上) -.s.signature.was.verified.=\u0020 s = 已验证签名\u0020 -.m.entry.is.listed.in.manifest=\u0020 m = 在清单中列出条目 -.k.at.least.one.certificate.was.found.in.keystore=\u0020 k = 在密钥库中至少找到了一个证书 -.X.not.signed.by.specified.alias.es.=\u0020 X = 未由指定别名签名 -.q.unsigned.entry=\u0020 ? = 未签名条目 +.s.signature.was.verified.=\ s = 已验证签名\u0020 +.m.entry.is.listed.in.manifest=\ m = 在清单中列出条目 +.k.at.least.one.certificate.was.found.in.keystore=\ k = 在密钥库中至少找到了一个证书 +.X.not.signed.by.specified.alias.es.=\ X = 未由指定别名签名 +.q.unsigned.entry=\ ? = 未签名条目 no.manifest.=没有清单。 .Signature.related.entries.=(与签名相关的条目) .Unsigned.entries.=(未签名条目) @@ -96,6 +96,7 @@ jar.is.unsigned=jar 未签名。 jar.treated.unsigned=警告: 签名无法解析或验证, 该 jar 将被视为未签名。有关详细信息, 请在启用调试的情况下重新运行 jarsigner (-J-Djava.security.debug=jar)。 jar.treated.unsigned.see.weak=由于该 jar 是使用目前已禁用的弱算法签名的, 因此该 jar 将被视为未签名。\n\n有关详细信息, 请使用 -verbose 选项重新运行 jarsigner。 jar.treated.unsigned.see.weak.verbose=警告: 该 jar 将被视为未签名, 因为它是由目前安全属性禁用的弱算法签名的: +multiple.manifest.warning.=在 jar 文件中检测到重复的清单条目。JarSigner 仅对其中一个条目进行了操作,其他条目都已放弃。 jar.signed.=jar 已签名。 jar.signed.with.signer.errors.=jar 已签名, 但出现签名者错误。 jar.verified.=jar 已验证。 @@ -103,28 +104,28 @@ jar.verified.with.signer.errors.=jar 已验证, 但出现签名者错误。 history.with.ts=- 由 "%1$s" 签名\n 摘要算法: %2$s\n 签名算法: %3$s, %4$s\n 由 "%6$s" 于 %5$tc 加时间戳\n 时间戳摘要算法: %7$s\n 时间戳签名算法: %8$s, %9$s history.without.ts=- 由 "%1$s" 签名\n 摘要算法: %2$s\n 签名算法: %3$s, %4$s -history.nonexistent.entries=警告:不存在的签名条目:\u0020 +history.nonexistent.entries=\ 警告:不存在的签名条目:\u0020 history.unparsable=- 无法解析的与签名相关的文件 %s history.nosf=- 缺少与签名相关的文件 META-INF/%s.SF history.nobk=- 与签名相关的文件 META-INF/%s.SF 缺少块文件 -with.weak=%s (弱) +with.weak=%s(弱) with.algparams.weak=%1$s 使用 %2$s(弱) with.disabled=%s(禁用) with.algparams.disabled=%1$s 使用 %2$s(禁用) key.bit=%s 密钥 key.bit.weak=%s 密钥(弱) -key.bit.disabled=%s 密钥(已禁用) +key.bit.disabled=%s 密钥(禁用) nonexistent.entries.found=此 jar 的文件包含不存在的签名条目。有关更多详细信息,请参见 -verbose 输出。 external.file.attributes.detected=检测到 POSIX 文件权限和/或 symlink 属性。这些属性在进行签名时会被忽略,不受该签名的保护。 -jarsigner.=jarsigner:\u0020 +jarsigner.=jarsigner:\u0020 signature.filename.must.consist.of.the.following.characters.A.Z.0.9.or.=签名文件名必须包含以下字符: A-Z, 0-9, _ 或 - unable.to.open.jar.file.=无法打开 jar 文件:\u0020 unable.to.create.=无法创建:\u0020 -.adding.=\u0020 正在添加:\u0020 -.updating.=\u0020正在更新:\u0020 -.signing.=\u0020 正在签名:\u0020 +.adding.=\ 正在添加:\u0020 +.updating.=\ 正在更新:\u0020 +.signing.=\ 正在签名:\u0020 attempt.to.rename.signedJarFile.to.jarFile.failed=尝试将{0}重命名为{1}时失败 attempt.to.rename.jarFile.to.origJar.failed=尝试将{0}重命名为{1}时失败 unable.to.sign.jar.=无法对 jar 进行签名:\u0020 @@ -151,12 +152,12 @@ certificate.will.expire.on=证书将在{0}到期 requesting.a.signature.timestamp=正在请求签名时间戳 TSA.location.=TSA 位置:\u0020 TSA.certificate.=TSA 证书:\u0020 -no.response.from.the.Timestamping.Authority.=时间戳颁发机构没有响应。如果要从防火墙后面连接, 则可能需要指定 HTTP 或 HTTPS 代理。请为 jarsigner 提供以下选项:\u0020 +no.response.from.the.Timestamping.Authority.=时间戳颁发机构没有响应。如果要从防火墙后面连接, 则可能需要指定 HTTP 或 HTTPS 代理。请为 jarsigner 提供以下选项: or=或 Certificate.not.found.for.alias.alias.must.reference.a.valid.KeyStore.entry.containing.an.X.509.public.key.certificate.for.the=找不到{0}的证书。{1}必须引用包含时间戳颁发机构的 X.509 公共密钥证书的有效密钥库条目。 entry.was.signed.on=条目的签名日期为 {0} -Warning.=警告:\u0020 -Error.=错误:\u0020 +Warning.=警告:\u0020 +Error.=错误:\u0020 ...Signer=>>> 签名者 ...TSA=>>> TSA trusted.certificate=可信证书 @@ -189,8 +190,8 @@ The.timestamp.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.w The.digest.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$s 摘要算法被视为存在安全风险。此算法将在未来的更新中被禁用。 The.signature.algorithm.1.is.considered.a.security.risk..This.algorithm.will.be.disabled.in.a.future.update.=%1$s 签名算法被视为存在安全风险。此算法将在未来的更新中被禁用。 size.bit.alg=%1$d 位 %2$s -The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=%s 签名密钥被视为安全风险。在将来的更新中将禁用它。 -The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=%s 签名密钥被视为安全风险并被禁用。 +The.full.keyAlgName.signing.key.is.considered.a.security.risk..It.will.be.disabled.in.a.future.update.=%s 签名密钥被视为存在安全风险。它将在未来的更新中被禁用。 +The.full.keyAlgName.signing.key.is.considered.a.security.risk.and.is.disabled.=%s 签名密钥被视为存在安全风险而且被禁用。 This.jar.contains.entries.whose.certificate.chain.is.invalid.reason.1=此 jar 包含其证书链无效的条目。原因: %s This.jar.contains.entries.whose.tsa.certificate.chain.is.invalid.reason.1=此 jar 包含其 TSA 证书链无效的条目。原因: %s no.timestamp.signing=未提供 -tsa 或 -tsacert, 此 jar 没有时间戳。如果没有时间戳, 则在签名者证书的到期日期 (%1$tY-%1$tm-%1$td) 之后, 用户可能无法验证此 jar。 @@ -205,3 +206,17 @@ Cannot.find.environment.variable.=找不到环境变量:\u0020 Cannot.find.file.=找不到文件:\u0020 event.ocsp.check=正在联系位于 %s 的 OCSP 服务器... event.crl.check=正在从 %s 下载 CRL... +manifest.missing.when.reading.jarfile=通过 JarFile 读取时缺少清单 +manifest.missing.when.reading.jarinputstream=通过 JarInputStream 读取时缺少清单 +manifest.attribute.1.present.when.reading.jarfile.but.missing.via.jarinputstream=通过 JarFile 读取时,清单主属性 %s 存在,但通过 JarInputStream 读取时缺失 +manifest.attribute.1.present.when.reading.jarinputstream.but.missing.via.jarfile=通过 JarInputStream 读取时,清单主属性 %s 存在,但通过 JarFile 读取时缺失 +manifest.attribute.1.differs.jarfile.value.2.jarinputstream.value.3=清单主属性 %1$s 不同:JarFile 值 = %2$s,JarInputStream 值 = %3$s +entry.1.present.when.reading.jarinputstream.but.missing.via.jarfile=通过 JarInputStream 读取时,条目 %s 存在,但通过 JarFile 读取时缺失 +entry.1.present.when.reading.jarfile.but.missing.via.jarinputstream=通过 JarFile 读取时,条目 %s 存在,但通过 JarInputStream 读取时缺失 +entry.1.present.in.jarfile.but.unreadable=条目 %s 存在于 JarFile 中,但无法读取 +codesigners.different.for.entry.1.when.reading.jarfile.and.jarinputstream=从 JarFile 和 JarInputStream 读取时,条目 %s 的代码签名者不同 +entry.1.is.signed.in.jarfile.but.is.not.signed.in.jarinputstream=条目 %s 已在 JarFile 中签名,但未在 JarInputStream 中签名 +entry.1.is.signed.in.jarinputstream.but.is.not.signed.in.jarfile=条目 %s 已在 JarInputStream 中签名,但未在 JarFile 中签名 +jar.contains.internal.inconsistencies.result.in.different.contents.via.jarfile.and.jarinputstream=此 JAR 文件包含内部不一致,通过 JarFile 和 JarInputStream 读取时可能会导致内容不同: +signature.verification.failed.on.entry.1.when.reading.via.jarinputstream=通过 JarInputStream 读取时,条目 %s 的签名验证失败 +signature.verification.failed.on.entry.1.when.reading.via.jarfile=通过 JarFile 读取时,条目 %s 的签名验证失败 diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties index e81bda89ef3..2a5786e10b4 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,7 @@ error.missing.provider=Serviceprovider nicht gefunden: {0} error.release.value.notnumber=Release {0} nicht gültig error.release.value.toosmall=Release {0} nicht gültig, muss >= 9 sein error.release.unexpected.versioned.entry=Unerwarteter versionierte Eintrag {0} für Release {1} +error.release.value.toohigh.versioned.entry={0} hat Klassendateiversion {1}, aber Klassendateiversion {2} oder niedriger ist für Release {3} der Java-Plattform erforderlich error.date.notvalid=Datum {0} ist keine gültige erweiterte Datums-/Uhrzeitangabe mit Zeitunterschied und optionaler Zeitzone nach ISO-8601 error.date.out.of.range=Datum {0} liegt nicht im gültigen Bereich 1980-01-01T00:00:02Z bis 2099-12-31T23:59:59Z error.validator.jarfile.exception={0} kann nicht validiert werden: {1} @@ -82,6 +83,12 @@ error.validator.info.manclass.notequal={0}: module-info.class in einem versionie warn.validator.identical.entry=Warnung: Eintrag {0} enthält eine Klasse, die mit\neinem bereits in der JAR-Datei enthaltenen Eintrag identisch ist warn.validator.resources.with.same.name=Warnung: Eintrag {0}, mehrere Ressourcen mit demselben Namen warn.validator.concealed.public.class=Warnung: Eintrag {0} ist eine öffentliche Klasse\nin einem verdeckten Package. Wenn Sie diese JAR-Datei in den Classpath einfügen, kommt es\nzu nicht kompatiblen öffentlichen Schnittstellen +warn.validator.duplicate.cen.entry=Warnung: {0} zentrale Verzeichniseinträge für {1} gefunden +warn.validator.duplicate.loc.entry=Warnung: {0} lokale Dateiheader für {1} gefunden +warn.validator.invalid.entry.name=Warnung: Eintragsname {0} ist ungültig +warn.validator.cen.only.entry=Warnung: Kein Äquivalent für zentralen Verzeichniseintrag {0} in den lokalen Dateiheadern gefunden +warn.validator.loc.only.entry=Warnung: Kein äquivalenter Eintrag für den lokalen Dateiheader {0} im zentralen Verzeichnis gefunden +warn.validator.order.mismatch=Warnung: Zentrale Verzeichniseinträge und lokale Dateiheadereinträge sind nicht in derselben Reihenfolge warn.release.unexpected.versioned.entry=Unerwarteter versionierter Eintrag {0} warn.index.is.ignored=Der JAR-Index (META-INF/INDEX.LIST) wird seit JDK 18 zur Laufzeit ignoriert warn.flag.is.deprecated=Warnung: Die Option {0} ist veraltet und wird möglicherweise ignoriert oder in einem zukünftigen Release entfernt\n @@ -115,7 +122,9 @@ main.help.opt.main.list=\ -t, --list Das Inhaltsverzeichnis fü main.help.opt.main.update=\ -u, --update Ein vorhandenes JAR-Archiv aktualisieren main.help.opt.main.extract=\ -x, --extract Extrahiert benannte (oder alle) Dateien aus dem Archiv.\n Wenn eine Datei mit demselben Namen mehrmals im\n Archiv enthalten ist, wird jede Kopie extrahiert. Dabei überschreiben (ersetzen) neuere Kopien\n ältere Kopien, es sei denn, "-k" ist angegeben. main.help.opt.main.describe-module=\ -d, --describe-module Gibt den Moduldeskriptor oder automatischen Modulnamen aus -main.help.opt.main.validate=\ --validate Validiert den Inhalt des JAR-Archivs. Diese Option\n validiert, dass die von einem Multi-Release-JAR-Archiv\n exportierte API über die verschiedenen Releaseversionen\n hinweg konsistent ist. +main.help.opt.main.validate=\ --validate Validiert den Inhalt des JAR-Archivs. Diese Option:\n - Validiert, dass die von einem Multi-Release-JAR-Archiv\n exportierte API über die verschiedenen Releaseversionen\n hinweg konsistent ist.\n - Gibt eine Warnung aus, wenn ungültige oder doppelte Dateinamen vorhanden sind + + main.help.opt.any=\ In jedem Modus gültige Vorgangsmodifikatoren:\n\n -C DIR Zum angegebenen Verzeichnis wechseln und die folgende\n Datei aufnehmen. Bei Verwendung im Extraktionsmodus wird\n die JAR-Datei in das angegebene Verzeichnis extrahiert main.help.opt.any.file=\ -f, --file=FILE Der Name der Archivdatei. Wenn Sie dies auslassen, wird entweder stdin oder\n stdout verwendet, je nach Vorgang\n --release VERSION Speichert alle der folgenden Dateien in einem versionierten Verzeichnis\n der JAR-Datei (d.h. META-INF/versions/VERSION/) main.help.opt.any.verbose=\ -v, --verbose Verbose-Ausgabe bei Standardausgabe generieren @@ -139,5 +148,4 @@ main.help.opt.other.help=\ -?, -h, --help[:compat] Gibt diese Meldung oder o main.help.opt.other.help-extra=\ --help-extra Hilfe zu zusätzlichen Optionen main.help.opt.other.version=\ --version Programmversion ausgeben main.help.postopt=\ Ein Archiv ist ein modulares JAR-Archiv, wenn der Moduldeskriptor "module-info.class"\n in der Root der angegebenen Verzeichnisse oder in der Root des JAR-Archivs selbst\n vorhanden ist. Die folgenden Vorgänge sind nur gültig, wenn Sie ein modulares JAR-Archiv\n erstellen oder ein vorhandenes nicht modulares JAR-Archiv aktualisieren: "--module-version",\n "--hash-modules" und "--modulepath".\n\n Obligatorische oder optionale Argumente zu langen Optionen sind auch für die jeweils\n zugehörigen kurzen Optionen obligatorisch oder optional. -main.help.opt.extract=\ Vorgangsmodifikatoren, die nur im Extraktionsmodus gültig sind:\n main.help.opt.extract.dir=\ --dir Verzeichnis, in das die JAR-Datei extrahiert wird diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties index 5be71c2e424..c7d7c14613a 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,7 @@ error.missing.provider=サービス・プロバイダが見つかりません: { error.release.value.notnumber=リリース{0}は有効ではありません error.release.value.toosmall=リリース{0}は有効ではありません。9以上である必要があります error.release.unexpected.versioned.entry=リリース{1}で予期しないバージョニング済エントリ{0} +error.release.value.toohigh.versioned.entry={0}にはクラス・ファイル・バージョン{1}がありますが、Javaプラットフォームのリリース{3}をターゲットとするにはクラス・ファイル・バージョン{2}以下が必要です error.date.notvalid=日付{0}が、オプションのタイムゾーンを指定した、有効なISO-8601の拡張オフセットの日時ではありません error.date.out.of.range=日付{0}が有効な範囲1980-01-01T00:00:02Z to 2099-12-31T23:59:59Zにありません error.validator.jarfile.exception={0}を検証できません: {1} @@ -82,6 +83,12 @@ error.validator.info.manclass.notequal={0}: バージョニングされたディ warn.validator.identical.entry=警告 : エントリ{0}には、jarにすでに存在する\nエントリと同じクラスが含まれます warn.validator.resources.with.same.name=警告 : エントリ{0}、同じ名前を持つ複数のリソース warn.validator.concealed.public.class=警告 : エントリ{0}は、隠しパッケージ内のpublicクラスです。\nクラスパスにこのjarを配置すると、互換性のない\npublicインタフェースが生成されます +warn.validator.duplicate.cen.entry=警告: {1}に対して{0}の中央ディレクトリ・エントリがありました +warn.validator.duplicate.loc.entry=警告: {1}に対して{0}のローカル・ファイル・ヘッダーがありました +warn.validator.invalid.entry.name=警告: エントリ名{0}が無効です +warn.validator.cen.only.entry=警告: 中央ディレクトリ・エントリ{0}と同等のものがローカル・ファイル・ヘッダーに見つかりませんでした +warn.validator.loc.only.entry=警告: ローカル・ファイル・ヘッダー{0}と同等のエントリが中央ディレクトリに見つかりませんでした +warn.validator.order.mismatch=警告: 中央ディレクトリとローカル・ファイル・ヘッダーのエントリが同じ順序ではありません warn.release.unexpected.versioned.entry=予期しないバージョニング済エントリ{0} warn.index.is.ignored=JDK 18以降、JAR索引(META-INF/INDEX.LIST)は実行時に無視されます warn.flag.is.deprecated=警告: {0}オプションは非推奨であり、今後のリリースで無視または削除される可能性があります\n @@ -115,7 +122,9 @@ main.help.opt.main.list=\ -t、--list アーカイブの内容 main.help.opt.main.update=\ -u、--update 既存のjarアーカイブを更新します main.help.opt.main.extract=\ -x、--extract 指定の(またはすべての)ファイルをアーカイブから抽出します。\n 同じ名前のファイルがアーカイブに複数回出現する場合、\n 各コピーが抽出され、後のコピーにより、前のコピーが\n 上書き(置換)されます(-kが指定されている場合以外)。 main.help.opt.main.describe-module=\ -d, --describe-module モジュール・ディスクリプタまたは自動モジュール名を出力します -main.help.opt.main.validate=\ --validate jarアーカイブの内容を検証します。このオプションは\n 複数リリースのjarアーカイブでエクスポートされたAPIが\n すべての異なるリリース・バージョンで一貫していることを\n 検証します。 +main.help.opt.main.validate=\ --validate jarアーカイブの内容を検証します。このオプションは\n - 複数リリースのjarアーカイブでエクスポートされたAPIが\n すべての異なるリリース・バージョンで一貫していることを\n 検証します。\n - 無効または重複するファイル名がある場合は警告を発行します + + main.help.opt.any=\ どのモードでも有効な操作修飾子:\n\n -C DIR 指定のディレクトリに変更し、次のファイルを\n 取り込みます。抽出モードで使用されている場合、jarを\n 指定のディレクトリに抽出します main.help.opt.any.file=\ -f、--file=FILE アーカイブ・ファイル名。省略した場合、stdinまたは\n stdoutのいずれかが操作に基づいて使用されます\n --release VERSION 次のすべてのファイルをjarのバージョニングされたディレクトリ\n (つまり、META-INF/versions/VERSION/)に配置します main.help.opt.any.verbose=\ -v、--verbose 標準出力に詳細な出力を生成します @@ -139,5 +148,4 @@ main.help.opt.other.help=\ -?、-h、--help[:compat] これ(オプショ main.help.opt.other.help-extra=\ --help-extra 追加オプションのヘルプを提供します main.help.opt.other.version=\ --version プログラム・バージョンを出力します main.help.postopt=\ モジュール・ディスクリプタ'module-info.class'が指定のディレクトリのルートまたは\n jarアーカイブ自体のルートにある場合、アーカイブはモジュラjarです。\n 次の操作は、モジュラjarの作成時または既存の非モジュラjarの更新時に\n のみ有効です: '--module-version'、\n '--hash-modules'および'--module-path'。\n\n ロング・オプションへの必須またはオプションの引数は、対応するショート・オプション\n に対しても必須またはオプションになります。 -main.help.opt.extract=\ 抽出モードでのみ有効な操作修飾子:\n main.help.opt.extract.dir=\ --dir jarが抽出されるディレクトリ diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties index 1f652d87029..1979f3e2386 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -58,6 +58,7 @@ error.missing.provider=未找到服务提供方: {0} error.release.value.notnumber=发行版 {0} 无效 error.release.value.toosmall=发行版 {0} 无效, 必须 >= 9 error.release.unexpected.versioned.entry=发行版 {1} 存在意外的版本化条目 {0} +error.release.value.toohigh.versioned.entry={0} 具有类文件版本 {1},但是 Java 平台的目标发行版 {3} 需要类文件版本 {2} 或更低版本 error.date.notvalid=日期 {0} 不是具有可选时区的有效 ISO-8601 扩展偏移日期时间 error.date.out.of.range=日期 {0} 不在 1980-01-01T00:00:02Z 到 2099-12-31T23:59:59Z 这一有效范围内 error.validator.jarfile.exception=无法验证 {0}: {1} @@ -82,6 +83,12 @@ error.validator.info.manclass.notequal={0}: 版本化目录中的 module-info.cl warn.validator.identical.entry=警告: 条目 {0} 包含与 jar 中的\n现有条目相同的类 warn.validator.resources.with.same.name=警告: 条目 {0}, 多个资源具有相同名称 warn.validator.concealed.public.class=警告: 条目 {0} 是已隐藏程序包中的\n公共类, 将此 jar 放置在类路径中\n将导致公共接口不兼容 +warn.validator.duplicate.cen.entry=警告:为 {1} 找到 {0} 个中央目录条目 +warn.validator.duplicate.loc.entry=警告:为 {1} 找到 {0} 个本地文件标头 +warn.validator.invalid.entry.name=警告:条目名称 {0} 无效 +warn.validator.cen.only.entry=警告:在本地文件标头中找不到中央目录条目 {0} 的等效条目 +warn.validator.loc.only.entry=警告:在中央目录中找不到本地文件标头 {0} 的等效条目 +warn.validator.order.mismatch=警告:中央目录和本地文件标头条目的顺序不同 warn.release.unexpected.versioned.entry=意外的版本化条目 {0} warn.index.is.ignored=自 JDK 18 起,在运行时忽略 JAR 索引 (META-INF/INDEX.LIST) warn.flag.is.deprecated=警告:{0} 选项已过时,可能会在未来发行版中忽略或删除。\n @@ -115,7 +122,9 @@ main.help.opt.main.list=\ -t, --list 列出档案的目录 main.help.opt.main.update=\ -u, --update 更新现有 jar 档案 main.help.opt.main.extract=\ -x, --extract 从档案中提取指定的(或所有)文件。\n 如果某个同名的文件在档案中出现多次,\n 则将提取每个副本,除非指定 -k,否则\n 后面的副本将覆盖(替换)前面的副本。 main.help.opt.main.describe-module=\ -d, --describe-module 输出模块描述符或自动模块名称 -main.help.opt.main.validate=\ --validate 验证 jar 档案的内容。此选项\n 将验证由多发行版 jar 档案导出\n 的 API 在所有不同的发行版本中\n 是否一致。 +main.help.opt.main.validate=\ --validate 验证 jar 档案的内容。此选项:\n - 验证由多发行版 jar 档案导出\n 的 API 在所有不同的发行版本中\n 是否一致。\n - 如果文件名无效或重复,则发出警告 + + main.help.opt.any=\ 在任意模式下有效的操作修饰符:\n\n -C DIR 更改为指定目录并包含\n 以下文件。在提取模式下使用时,\n 将 jar 提取到指定目录 main.help.opt.any.file=\ -f, --file=FILE 档案文件名。省略时, 基于操作\n 使用 stdin 或 stdout\n --release VERSION 将下面的所有文件都放在\n jar 的版本化目录中 (即 META-INF/versions/VERSION/) main.help.opt.any.verbose=\ -v, --verbose 在标准输出中生成详细输出 @@ -139,5 +148,4 @@ main.help.opt.other.help=\ -?, -h, --help[:compat] 提供此帮助,也可 main.help.opt.other.help-extra=\ --help-extra 提供额外选项的帮助 main.help.opt.other.version=\ --version 输出程序版本 main.help.postopt=\ 如果模块描述符 'module-info.class' 位于指定目录的\n 根目录中, 或者位于 jar 档案本身的根目录中, 则\n 该档案是一个模块化 jar。以下操作只在创建模块化 jar,\n 或更新现有的非模块化 jar 时有效: '--module-version',\n '--hash-modules' 和 '--module-path'。\n\n 如果为长选项提供了必需参数或可选参数, 则它们对于\n 任何对应的短选项也是必需或可选的。 -main.help.opt.extract=\ 仅在提取模式下有效的操作修饰符:\n main.help.opt.extract.dir=\ --dir jar 将提取到其中的目录 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties index b4d3f94bad5..a725d415406 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -97,6 +97,9 @@ doclet.Record_component_in=Komponente von {0} erfassen doclet.Static_method_in=Statische Methode in {0} doclet.Search_tag_in=Tag suchen in {0} doclet.Method_in=Methode in {0} +doclet.System_property_in=Systemeigenschaft in {0} +doclet.External_specification_in=Externe Spezifikation in {0} +doclet.Section_in=Abschnitt in {0} doclet.module=Modul doclet.package=Package doclet.MalformedURL=Nicht wohlgeformte URL: {0} @@ -116,14 +119,14 @@ doclet.tag.invalid_input=Ungültige Eingabe: "{0}" doclet.tag.invalid=ungültiges @{0} doclet.Deprecated_API=Veraltete API doclet.Deprecated_API_Checkbox_Label=Veraltete API anzeigen in: -doclet.Deprecated_API_Checkbox_All_Releases=Alle +doclet.Deprecated_API_Checkbox_All_Releases=Alle umschalten doclet.Deprecated_API_Checkbox_Other_Releases=Sonstige doclet.Deprecated_Elements=Veraltete {0} doclet.Deprecated_Elements_Release_Column_Header=Veraltet in doclet.Deprecated_In_Release=Veraltet in {0} doclet.New_API=Neue API doclet.New_API_Checkbox_Label=Hinzugefügte API anzeigen in: -doclet.New_API_Checkbox_All_Releases=Alle +doclet.New_API_Checkbox_All_Releases=Alle umschalten doclet.New_Elements=Neue {0} doclet.New_Elements_Release_Column_Header=Hinzugefügt in doclet.New_Label=Neu @@ -133,6 +136,8 @@ doclet.Preview_API_Checkbox_Toggle_All=Alle umschalten doclet.Preview_JEP_URL=https://openjdk.org/jeps/{0} doclet.Preview_Label=Vorschau doclet.Preview_Mark=PREVIEW +doclet.Preview_Notes=Hinweise zur Vorschau-API +doclet.Preview_Notes_Elements=Elemente mit Vorschauhinweisen doclet.Restricted_Methods=Eingeschränkte Methoden doclet.Restricted_Mark=RESTRICTED doclet.searchTag=Suchtag @@ -174,13 +179,11 @@ doclet.Enclosing_Interface=Umschließende Schnittstelle: doclet.Inheritance_Tree=Vererbungsbaum doclet.DefinedIn=Definiert in doclet.ReferencedIn=Referenziert in -doclet.Section=Abschnitt -doclet.External_Specification=Externe Spezifikation doclet.External_Specifications=Externe Spezifikationen doclet.External_Specifications.All_Specifications=Alle Spezifikationen doclet.External_Specifications.no-host=Lokal doclet.Specification=Spezifikation -doclet.System_Property=Systemeigenschaft +doclet.Summary_Page=Zusammenfassung (Seite) doclet.systemProperties=Systemeigenschaften doclet.systemPropertiesSummary=Systemeigenschaften - Übersicht doclet.Window_Source_title=Quellcode @@ -195,8 +198,9 @@ doclet.search.show_more=Zusätzliche Ressourcen doclet.search.help_page_link=Hilfeseite # 0: a link to the help page with text above doclet.search.help_page_info= Die {0} enthält eine Einführung in den Umfang und die Syntax der JavaDoc-Suche. -doclet.search.keyboard_info= Sie können die - oder -Taste zusammen mit den Pfeiltasten nach links und rechts verwenden, um zwischen Ergebnisregisterkarten auf dieser Seite zu wechseln. -doclet.search.browser_info= Mit der URL-Vorlage unten können Sie diese Seite als Suchmaschine in Browsern konfigurieren, die dieses Feature unterstützen. Das Feature wurde erfolgreich mit Google Chrome und Mozilla Firefox getestet. Beachten Sie, dass andere Browser dieses Feature möglicherweise nicht unterstützen oder ein anderes URL-Format erfordern. +# 0: [V] 1: [^] 2: [<]/[>] (down, up, left and right arrow keys) +doclet.search.keyboard_info= Sie können mit den Tasten {0}/{1} zwischen Suchergebnissen und mit den Tasten {2} zwischen Ergebnisregisterkarten wechseln. +doclet.search.browser_info= Die unten stehende URL-Vorlage kann nützlich sein, um diese Seite als Suchmaschine oder Bookmarklet in Browsern zu konfigurieren, die dieses Feature unterstützen. doclet.search.redirect=Zum ersten Ergebnis umleiten # 0: a date @@ -286,7 +290,18 @@ doclet.help.search.refer=Eine vollständige Beschreibung der Suchfeatures finden doclet.help.search.spec.url=https://docs.oracle.com/en/java/javase/{0}/docs/specs/javadoc/javadoc-search-spec.html # The title for the Javadoc Search Specification doclet.help.search.spec.title=Javadoc-Suchspezifikation - +doclet.help.keyboard_navigation.title=Tastaturnavigation +doclet.help.keyboard_navigation.intro=Dokumentationsseiten enthalten Tastenkombinationen für den einfachen Zugriff auf häufige Navigationsaufgaben. +# Arguments in the messages below are elements representing various keyboard keys +doclet.help.keyboard_navigation.index=Verwenden Sie {0}, um auf einer beliebigen Seite auf das Sucheingabefeld zuzugreifen. +doclet.help.keyboard_navigation.filter=Verwenden Sie {0}, um in der Randleiste von Klassenseiten auf das Filtereingabefeld zuzugreifen. +doclet.help.keyboard_navigation.escape=Verwenden Sie {0}, um die Eingabe zu löschen und den Tastaturfokus von einem Eingabefeld zu entfernen. +doclet.help.keyboard_navigation.search=Verwenden Sie {0}/{1}/{2}, um Listenelemente auszuwählen, nachdem Sie einen Suchbegriff in ein Such- oder Filtereingabefeld eingegeben haben. +doclet.help.keyboard_navigation.tabs=Verwenden Sie {0}/{1}, um in Zusammenfassungstabellen mit Registerkarten zwischen Registerkarten zu wechseln. +doclet.help.releases.head=Releasedetails +doclet.help.releases.body.specify.top-level=Die Details für die einzelnen Module, Packages, Klassen oder Schnittstellen enthalten normalerweise das Release, in dem die Deklaration eingeführt wurde. +doclet.help.releases.body.specify.member=Wenn ein Member nach der anfänglichen Einführung der umschließenden Klasse oder Schnittstelle hinzugefügt wird, enthalten die Details des Members das Release, in dem es eingeführt wurde. +doclet.help.releases.body.refer=Auf einigen Übersichtsseiten ("Neue API", "Veraltet") können Sie den Inhalt der Seite nach dem Release filtern, in dem die Deklaration eingeführt oder eingestellt wurde. doclet.ClassUse_Packages.that.use.0=Packages, die {0} verwenden doclet.ClassUse_Uses.of.0.in.1=Verwendungen von {0} in {1} doclet.ClassUse_Classes.in.0.used.by.1=Von {1} verwendete Klassen in {0} @@ -501,6 +516,8 @@ doclet.usage.override-methods.description=Außer Kraft gesetzte Methoden im Absc doclet.usage.allow-script-in-comments.description=JavaScript in Dokumentationskommentaren und Optionen\nzulassen, die HTML-Code enthalten +doclet.usage.syntax-highlight.description=Syntaxhervorhebung für Codefragmente in {@snippet}-Tags\nund
    -Elementen aktivieren.
    +
     doclet.usage.xdocrootparent.parameters=< URL>
     doclet.usage.xdocrootparent.description=Ersetzt alle Vorkommen von @docRoot gefolgt von /.. in doc-Kommentaren durch\n
     
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties
    index 31e745301b6..749ef5856b8 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -97,6 +97,9 @@ doclet.Record_component_in={0}のレコード・コンポーネント
     doclet.Static_method_in={0}のstaticメソッド
     doclet.Search_tag_in={0}の検索タグ
     doclet.Method_in={0}のメソッド
    +doclet.System_property_in={0}のシステム・プロパティ
    +doclet.External_specification_in={0}の外部仕様
    +doclet.Section_in={0}のセクション
     doclet.module=モジュール
     doclet.package=パッケージ
     doclet.MalformedURL=不正なURL: {0}
    @@ -116,14 +119,14 @@ doclet.tag.invalid_input=入力が無効です: ''{0}''
     doclet.tag.invalid=@{0}が無効です
     doclet.Deprecated_API=推奨されていないAPI
     doclet.Deprecated_API_Checkbox_Label=次で非推奨のAPIを表示:
    -doclet.Deprecated_API_Checkbox_All_Releases=すべて
    +doclet.Deprecated_API_Checkbox_All_Releases=すべて設定
     doclet.Deprecated_API_Checkbox_Other_Releases=その他
     doclet.Deprecated_Elements=推奨されていない{0}
     doclet.Deprecated_Elements_Release_Column_Header=次で非推奨
     doclet.Deprecated_In_Release={0}で非推奨
     doclet.New_API=新規API
     doclet.New_API_Checkbox_Label=次で追加されたAPIを表示:
    -doclet.New_API_Checkbox_All_Releases=すべて
    +doclet.New_API_Checkbox_All_Releases=すべて設定
     doclet.New_Elements=新規{0}
     doclet.New_Elements_Release_Column_Header=次で追加
     doclet.New_Label=新規
    @@ -133,6 +136,8 @@ doclet.Preview_API_Checkbox_Toggle_All=すべて設定
     doclet.Preview_JEP_URL=https://openjdk.org/jeps/{0}
     doclet.Preview_Label=プレビュー
     doclet.Preview_Mark=PREVIEW
    +doclet.Preview_Notes=プレビューAPIのノート
    +doclet.Preview_Notes_Elements=プレビュー・ノートを含む要素
     doclet.Restricted_Methods=制限されたメソッド
     doclet.Restricted_Mark=RESTRICTED
     doclet.searchTag=検索タグ
    @@ -174,13 +179,11 @@ doclet.Enclosing_Interface=含まれているインタフェース:
     doclet.Inheritance_Tree=継承ツリー
     doclet.DefinedIn=定義先
     doclet.ReferencedIn=参照
    -doclet.Section=セクション
    -doclet.External_Specification=外部仕様
     doclet.External_Specifications=外部仕様
     doclet.External_Specifications.All_Specifications=すべての仕様
     doclet.External_Specifications.no-host=ローカル
     doclet.Specification=仕様
    -doclet.System_Property=システム・プロパティ
    +doclet.Summary_Page=サマリー・ページ
     doclet.systemProperties=システム・プロパティ
     doclet.systemPropertiesSummary=システム・プロパティ・サマリー
     doclet.Window_Source_title=ソース・コード
    @@ -195,8 +198,9 @@ doclet.search.show_more=その他のリソース
     doclet.search.help_page_link=ヘルプ・ページ
     # 0: a link to the help page with text above
     doclet.search.help_page_info= {0}では、JavaDoc検索の範囲および構文の概要について説明します。
    -doclet.search.keyboard_info= またはキーを左右の矢印キーと組み合せて使用すると、このページの結果タブを切り替えることができます。
    -doclet.search.browser_info= 次のURLテンプレートは、この機能をサポートするブラウザでこのページを検索エンジンとして構成するために使用できます。Google ChromeおよびMozilla Firefoxで動作することがテストされています。他のブラウザでは、この機能がサポートされていないか、別のURL形式が必要になる場合があります。
    +# 0: [V] 1: [^] 2: [<]/[>] (down, up, left and right arrow keys)
    +doclet.search.keyboard_info= {0}/{1}キーを使用して検索結果間を移動し、{2}キーを使用して結果タブ間を切り替えます。
    +doclet.search.browser_info= 下のURLテンプレートは、この機能をサポートするブラウザで検索エンジンまたはブックマークとして、このページを構成するのに役立つ可能性があります。
     doclet.search.redirect=最初の結果にリダイレクト
     
     # 0: a date
    @@ -286,7 +290,18 @@ doclet.help.search.refer=検索機能の詳細な説明は、{0}を参照して
     doclet.help.search.spec.url=https://docs.oracle.com/en/java/javase/{0}/docs/specs/javadoc/javadoc-search-spec.html
     # The title for the Javadoc Search Specification
     doclet.help.search.spec.title=Javadoc検索仕様
    -
    +doclet.help.keyboard_navigation.title=キーボード・ナビゲーション
    +doclet.help.keyboard_navigation.intro=ドキュメント・ページは、一般的なナビゲーション・タスクへのアクセスを容易にするキーボード・ショートカットを提供します。
    +# Arguments in the messages below are  elements representing various keyboard keys
    +doclet.help.keyboard_navigation.index=任意のページの検索入力フィールドにアクセスするには{0}と入力します。
    +doclet.help.keyboard_navigation.filter=クラス・ページのサイドバーのフィルタ入力フィールドにアクセスするには{0}と入力します。
    +doclet.help.keyboard_navigation.escape=任意の入力フィールドの入力をクリアし、キーボード・フォーカスを解放するには{0}と入力します。
    +doclet.help.keyboard_navigation.search=検索またはフィルタ入力フィールドに検索語を入力した後でリスト項目を選択するには{0}/{1}/{2}と入力します。
    +doclet.help.keyboard_navigation.tabs=タブ付きサマリー表のタブ間を切り替えるには{0}/{1}と入力します。
    +doclet.help.releases.head=リリース詳細
    +doclet.help.releases.body.specify.top-level=各モジュール、パッケージ、クラスまたはインタフェースの詳細には、通常、宣言が導入されたリリースが含まれます。
    +doclet.help.releases.body.specify.member=含まれているクラスまたはインタフェースの初期導入後にメンバーが追加された場合、メンバーの詳細にはそれが導入されたリリースが含まれます。
    +doclet.help.releases.body.refer=一部のサマリー・ページ(新規API、非推奨)では、宣言が導入または非推奨化されたリリースに従ってページのコンテンツをフィルタできます。
     doclet.ClassUse_Packages.that.use.0={0}を使用しているパッケージ
     doclet.ClassUse_Uses.of.0.in.1={1}での{0}の使用
     doclet.ClassUse_Classes.in.0.used.by.1={1}により使用される{0}のクラス
    @@ -501,6 +516,8 @@ doclet.usage.override-methods.description=オーバーライドされたメソ
     
     doclet.usage.allow-script-in-comments.description=ドキュメント・コメント、および値がhtml-codeであるオプションで\nJavaScriptを許可します
     
    +doclet.usage.syntax-highlight.description={@snippet}タグおよび
    要素のコード・フラグメントの\n構文ハイライト表示を有効にします。
    +
     doclet.usage.xdocrootparent.parameters=
     doclet.usage.xdocrootparent.description=docコメント内の/..が後に続く@docRootのすべてをで置換します
     
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties
    index 36e27355b63..4bb154065b6 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -97,6 +97,9 @@ doclet.Record_component_in={0} 的记录组件
     doclet.Static_method_in={0}中的静态方法
     doclet.Search_tag_in={0}中的搜索标记
     doclet.Method_in={0}中的方法
    +doclet.System_property_in={0} 中的系统属性
    +doclet.External_specification_in={0} 中的外部规范
    +doclet.Section_in={0} 中的节
     doclet.module=模块
     doclet.package=程序包
     doclet.MalformedURL=格式错误的 URL: {0}
    @@ -116,14 +119,14 @@ doclet.tag.invalid_input=无效输入:''{0}''
     doclet.tag.invalid=@{0} 无效
     doclet.Deprecated_API=已过时的 API
     doclet.Deprecated_API_Checkbox_Label=显示在以下发行版中已过时的 API:
    -doclet.Deprecated_API_Checkbox_All_Releases=全部
    +doclet.Deprecated_API_Checkbox_All_Releases=全部切换
     doclet.Deprecated_API_Checkbox_Other_Releases=其他
     doclet.Deprecated_Elements=已过时的 {0}
     doclet.Deprecated_Elements_Release_Column_Header=在以下发行版中已过时
     doclet.Deprecated_In_Release=在 {0} 中已过时
     doclet.New_API=新建 API
     doclet.New_API_Checkbox_Label=显示在以下发行版中添加的 API:
    -doclet.New_API_Checkbox_All_Releases=全部
    +doclet.New_API_Checkbox_All_Releases=全部切换
     doclet.New_Elements=新建 {0}
     doclet.New_Elements_Release_Column_Header=在以下发行版中已添加
     doclet.New_Label=新建
    @@ -133,6 +136,8 @@ doclet.Preview_API_Checkbox_Toggle_All=全部切换
     doclet.Preview_JEP_URL=https://openjdk.org/jeps/{0}
     doclet.Preview_Label=预览
     doclet.Preview_Mark=PREVIEW
    +doclet.Preview_Notes=预览 API 注释
    +doclet.Preview_Notes_Elements=包含预览注释的元素
     doclet.Restricted_Methods=受限制的方法
     doclet.Restricted_Mark=RESTRICTED
     doclet.searchTag=搜索标记
    @@ -174,13 +179,11 @@ doclet.Enclosing_Interface=封闭接口:
     doclet.Inheritance_Tree=继承树
     doclet.DefinedIn=定义位置
     doclet.ReferencedIn=参考位置
    -doclet.Section=节
    -doclet.External_Specification=外部规范
     doclet.External_Specifications=外部规范
     doclet.External_Specifications.All_Specifications=所有规范
     doclet.External_Specifications.no-host=本地
     doclet.Specification=规范
    -doclet.System_Property=系统属性
    +doclet.Summary_Page=概要页
     doclet.systemProperties=系统属性
     doclet.systemPropertiesSummary=系统属性概要
     doclet.Window_Source_title=源代码
    @@ -195,8 +198,9 @@ doclet.search.show_more=其他资源
     doclet.search.help_page_link=帮助页
     # 0: a link to the help page with text above
     doclet.search.help_page_info= {0} 介绍了 JavaDoc 搜索的范围和语法。
    -doclet.search.keyboard_info= 您可以使用  键与左箭头和右箭头键组合在此页面中的结果选项卡之间切换。
    -doclet.search.browser_info= 下面的 URL 模板可用于在支持此功能的浏览器中将此页面配置为搜索引擎。已经对其进行了测试以在 Google Chrome 和 Mozilla Firefox 中使用。请注意,其他浏览器可能不支持此功能或需要不同的 URL 格式。
    +# 0: [V] 1: [^] 2: [<]/[>] (down, up, left and right arrow keys)
    +doclet.search.keyboard_info= 使用 {0}/{1} 键在搜索结果之间移动,使用 {2} 键在结果选项卡之间切换。
    +doclet.search.browser_info= 下面的 URL 模板可能有助于在支持此功能的浏览器中将此页面配置为搜索引擎或 bookmarklet。
     doclet.search.redirect=重定向到第一个结果
     
     # 0: a date
    @@ -286,7 +290,18 @@ doclet.help.search.refer=有关搜索功能的完整说明,请参阅 {0}。
     doclet.help.search.spec.url=https://docs.oracle.com/en/java/javase/{0}/docs/specs/javadoc/javadoc-search-spec.html
     # The title for the Javadoc Search Specification
     doclet.help.search.spec.title=Javadoc 搜索规范
    -
    +doclet.help.keyboard_navigation.title=键盘导航
    +doclet.help.keyboard_navigation.intro=文档页面提供键盘快捷键,以方便访问常见的导航任务。
    +# Arguments in the messages below are  elements representing various keyboard keys
    +doclet.help.keyboard_navigation.index=键入 {0} 以访问任何页面中的搜索输入字段。
    +doclet.help.keyboard_navigation.filter=键入 {0} 以访问类页面子工具栏中的筛选器输入字段。
    +doclet.help.keyboard_navigation.escape=键入 {0} 以清除任何输入字段中的输入并释放键盘焦点。
    +doclet.help.keyboard_navigation.search=在搜索或筛选器输入字段中输入搜索词后,键入 {0}/{1}/{2} 以选择列表项。
    +doclet.help.keyboard_navigation.tabs=键入 {0}/{1} 以在选项卡式概要表中的选项卡之间切换。
    +doclet.help.releases.head=发行版详细信息
    +doclet.help.releases.body.specify.top-level=每个模块、程序包、类或接口的详细信息通常包括引入声明的发行版。
    +doclet.help.releases.body.specify.member=当在最初引入封闭类或接口后添加成员时,成员的详细信息包括引入它的发行版。
    +doclet.help.releases.body.refer=某些概要页(新建 API、已过时)允许您根据声明被引入或已过时的发行版筛选页面的内容。
     doclet.ClassUse_Packages.that.use.0=使用{0}的程序包
     doclet.ClassUse_Uses.of.0.in.1={1}中{0}的使用
     doclet.ClassUse_Classes.in.0.used.by.1={1}使用的{0}中的类
    @@ -501,6 +516,8 @@ doclet.usage.override-methods.description=在详细信息部分或概要部分
     
     doclet.usage.allow-script-in-comments.description=允许在文档注释和选项中使用 JavaScript\n其值为 html-code
     
    +doclet.usage.syntax-highlight.description=为 {@snippet} 标记和 
     元素中的代码片段\n启用语法突出显示。
    +
     doclet.usage.xdocrootparent.parameters=
     doclet.usage.xdocrootparent.description=将文档注释中出现的所有后跟 /.. 的 @docRoot 替换为\n
     
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties
    index 7ab2d3fc1dc..0ee34071c93 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -218,14 +218,15 @@ doclet.Annotation_Type_Optional_Members=Optionale Elemente
     doclet.Annotation_Type_Required_Members=Erforderliche Elemente
     doclet.Enum_Constants=Enum-Konstanten
     doclet.Nested_Classes=Verschachtelte Klassen
    -doclet.Modifier=Modifizierer
    +doclet.Modifier=Modifikator
     doclet.Type=Typ
    -doclet.Modifier_and_Type=Modifizierer und Typ
    +doclet.Modifier_and_Type=Modifikator und Typ
     doclet.Implementation=Implementierung(en):
     doclet.search=Suchen
    -doclet.search_placeholder=Suchen
    +doclet.search_placeholder=In Dokumentation suchen ("/" eingeben)
     doclet.search_in_documentation=In Dokumentation suchen
     doclet.search_reset=Zurücksetzen
    +doclet.Member=Mitglied
     doclet.Field=Feld
     doclet.Property=Eigenschaft
     doclet.Constructor=Konstruktor
    @@ -241,7 +242,7 @@ doclet.Value=Wert
     doclet.table_of_contents=Inhaltsverzeichnis
     doclet.hide_sidebar=Randleiste ausblenden
     doclet.show_sidebar=Randleiste einblenden
    -doclet.filter_label=Filter
    +doclet.filter_label=Inhalt filtern ("." eingeben)
     doclet.filter_table_of_contents=Inhaltsverzeichnis filtern
     doclet.filter_reset=Zurücksetzen
     doclet.linkMismatch_PackagedLinkedtoModule=Der Code, der dokumentiert wird, verwendet Packages im unbenannten Modul, aber die in {0} definierten Packages befinden sich in benannten Modulen.
    @@ -313,12 +314,16 @@ doclet.search.many_results={0} Ergebnisse gefunden
     doclet.search.loading=Suchindex wird geladen...
     doclet.search.searching=Suche wird ausgeführt...
     doclet.search.redirecting=Zum ersten Ergebnis wird umgeleitet...
    +# {0} is a select input containing all_modules message below and module names
    +doclet.search.in=in {0}
    +doclet.search.all_modules=allen Modulen
     doclet.search.modules=Module
     doclet.search.packages=Packages
     doclet.search.classes_and_interfaces=Klassen und Schnittstellen
     doclet.search.types=Typen
     doclet.search.members=Mitglieder
     doclet.search.search_tags=Tags suchen
    +doclet.search.linkSearchPageLabel=Gehe zur Suchseite
     
     doclet.snippet.contents.none=@snippet gibt keinen Inhalt an
     
    @@ -353,3 +358,6 @@ doclet.cannot_use_snippet_path=Option --snippet-path kann mit dem gegebenen Date
     
     # 0: path; 1: exception
     doclet.error_setting_snippet_path=Fehler beim Festlegen von Snippet-Pfad {0}: {1}
    +
    +# 0: location
    +doclet.error.snippet.ambiguous.link=Snippet-Linktags: {0} und {1} überschneiden sich in {2}
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties
    index 28126387ead..2b10f4e6e9a 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -223,9 +223,10 @@ doclet.Type=タイプ
     doclet.Modifier_and_Type=修飾子とタイプ
     doclet.Implementation=実装:
     doclet.search=検索
    -doclet.search_placeholder=検索
    +doclet.search_placeholder=ドキュメントの検索(/と入力)
     doclet.search_in_documentation=ドキュメントで検索
     doclet.search_reset=リセット
    +doclet.Member=メンバー
     doclet.Field=フィールド
     doclet.Property=プロパティ
     doclet.Constructor=コンストラクタ
    @@ -241,7 +242,7 @@ doclet.Value=値
     doclet.table_of_contents=目次
     doclet.hide_sidebar=サイドバーの非表示
     doclet.show_sidebar=サイドバーの表示
    -doclet.filter_label=フィルタ
    +doclet.filter_label=コンテンツのフィルタ(.と入力)
     doclet.filter_table_of_contents=目次のフィルタ
     doclet.filter_reset=リセット
     doclet.linkMismatch_PackagedLinkedtoModule=ドキュメント化しようとしているコードでは名前のないモジュールのパッケージが使用されていますが、{0}で定義されているパッケージは名前のあるモジュールのものです。
    @@ -313,12 +314,16 @@ doclet.search.many_results={0}の結果が見つかりました
     doclet.search.loading=検索索引をロード中...
     doclet.search.searching=検索中...
     doclet.search.redirecting=最初の結果にリダイレクト中...
    +# {0} is a select input containing all_modules message below and module names
    +doclet.search.in={0}内
    +doclet.search.all_modules=すべてのモジュール
     doclet.search.modules=モジュール
     doclet.search.packages=パッケージ
     doclet.search.classes_and_interfaces=クラスとインタフェース
     doclet.search.types=タイプ
     doclet.search.members=メンバー
     doclet.search.search_tags=タグの検索
    +doclet.search.linkSearchPageLabel=検索ページに移動します
     
     doclet.snippet.contents.none=@snippetにコンテンツが指定されていません
     
    @@ -353,3 +358,6 @@ doclet.cannot_use_snippet_path=指定されたファイル・マネージャで'
     
     # 0: path; 1: exception
     doclet.error_setting_snippet_path=スニペットのパス{0}の設定中にエラーが発生しました: {1}
    +
    +# 0: location
    +doclet.error.snippet.ambiguous.link=スニペット・リンク・タグ: {2}の{0}と{1}の重複
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties
    index e2722f1deab..f2c8762b283 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -223,9 +223,10 @@ doclet.Type=类型
     doclet.Modifier_and_Type=修饰符和类型
     doclet.Implementation=实现:
     doclet.search=搜索
    -doclet.search_placeholder=搜索
    +doclet.search_placeholder=搜索文档(键入 /)
     doclet.search_in_documentation=在文档中搜索
     doclet.search_reset=重置
    +doclet.Member=成员
     doclet.Field=字段
     doclet.Property=属性
     doclet.Constructor=构造器
    @@ -241,7 +242,7 @@ doclet.Value=值
     doclet.table_of_contents=目录
     doclet.hide_sidebar=隐藏子工具栏
     doclet.show_sidebar=显示子工具栏
    -doclet.filter_label=筛选器
    +doclet.filter_label=筛选内容(键入 .)
     doclet.filter_table_of_contents=筛选目录
     doclet.filter_reset=重置
     doclet.linkMismatch_PackagedLinkedtoModule=进行文档化的代码使用了未命名模块中的程序包,但在 {0} 中定义的程序包在命名模块中。
    @@ -313,12 +314,16 @@ doclet.search.many_results=找到 {0} 个结果
     doclet.search.loading=正在加载搜索索引...
     doclet.search.searching=正在搜索...
     doclet.search.redirecting=正在重定向到第一个结果...
    +# {0} is a select input containing all_modules message below and module names
    +doclet.search.in=在 {0} 中
    +doclet.search.all_modules=全部模块
     doclet.search.modules=模块
     doclet.search.packages=程序包
     doclet.search.classes_and_interfaces=类和接口
     doclet.search.types=类型
     doclet.search.members=成员
     doclet.search.search_tags=搜索标记
    +doclet.search.linkSearchPageLabel=转至搜索页
     
     doclet.snippet.contents.none=@snippet 未指定内容
     
    @@ -353,3 +358,6 @@ doclet.cannot_use_snippet_path=不能将 ''--snippet-path'' 选项与给定的
     
     # 0: path; 1: exception
     doclet.error_setting_snippet_path=设置片段路径 {0} 时出错:{1}
    +
    +# 0: location
    +doclet.error.snippet.ambiguous.link=片段链接标记:{0} 和 {1} 在 {2} 中重叠
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties
    index 4d0e7bae176..7829d2d7e27 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -32,6 +32,8 @@ main.warning={0} Warnung
     
     main.usage=Verwendung:\n    javadoc [options] [packagenames] [sourcefiles] [@files]\nmit folgenden Optionen:
     
    +main.usage.short=Verwendung:\n    javadoc [options] [packagenames] [sourcefiles] [@files]
    +
     main.did-you-mean=Meinten Sie: {0}
     
     main.did-you-mean-one-of=Meinten Sie eine der folgenden Optionen: {0}
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties
    index 42765ab4ded..da267939d3e 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -32,6 +32,8 @@ main.warning=警告{0}個
     
     main.usage=使用方法:\n    javadoc [options] [packagenames] [sourcefiles] [@files]\nオプションは次のとおりです:
     
    +main.usage.short=使用方法:\n    javadoc [options] [packagenames] [sourcefiles] [@files]
    +
     main.did-you-mean=もしかして: {0}
     
     main.did-you-mean-one-of=もしかして次のいずれかですか: {0}
    diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties
    index 27053b44753..0305eaf7743 100644
    --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties
    +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -32,6 +32,8 @@ main.warning={0} 个警告
     
     main.usage=用法:\n    javadoc [options] [packagenames] [sourcefiles] [@files]\n其中, 选项包括:
     
    +main.usage.short=用法:\n    javadoc [options] [packagenames] [sourcefiles] [@files]
    +
     main.did-you-mean=您要查找的是:{0}
     
     main.did-you-mean-one-of=您要查找的是以下项之一:{0}
    diff --git a/src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_de.properties b/src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_de.properties
    index 947fb1c8d66..e6859fd8d74 100644
    --- a/src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_de.properties
    +++ b/src/jdk.jconsole/share/classes/sun/tools/jconsole/resources/messages_de.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java
    index f3aadd3677c..04ec27a624d 100644
    --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java
    +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    diff --git a/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_de.properties
    new file mode 100644
    index 00000000000..fd30f5385e8
    --- /dev/null
    +++ b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_de.properties
    @@ -0,0 +1,68 @@
    +#
    +# Copyright (c) 2015, 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.  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.
    +#
    +
    +main.usage.summary=Verwendung: {0}   jimage...\nMit -h oder --help können Sie eine Liste der möglichen Optionen aufrufen.
    +
    +main.usage=Verwendung: {0}   jimage...\n\n  extract  - Extrahiert alle jimage-Einträge und platziert sie in einem mit der Option\n             --dir= (Standardwert = ".") angegebenen Verzeichnis.\n\n  info     - Gibt detaillierte Informationen aus, die im jimage-Header enthalten sind.\n\n  list     - Gibt die Namen aller Einträge im jimage aus. Bei Verwendung mit\n             --verbose gibt der Befehl "list" auch die Eintragsgröße und Offset-Attribute aus.\n\n  verify   - Meldet alle .class-Einträge, die nicht als Klassen verifiziert werden.\n\nMögliche Optionen:
    +
    +main.usage.extract=\  extract  - Extrahiert alle jimage-Einträge und platziert sie in einem mit der Option\n             --dir= (Standardwert = ".") angegebenen Verzeichnis.
    +
    +main.usage.info=\  info     - Gibt detaillierte Informationen aus, die im jimage-Header enthalten sind.
    +
    +main.usage.list=\  list     - Gibt die Namen aller Einträge im jimage aus. Bei Verwendung mit\n             --verbose gibt der Befehl "list" auch die Eintragsgröße und Offset-Attribute aus.
    +
    +main.usage.verify=\  verify   - Meldet alle .class-Einträge, die nicht als Klassen verifiziert werden.
    +
    +error.prefix=Fehler:
    +warn.prefix=Warnung:
    +
    +main.opt.dir=\          --dir                        Zielverzeichnis für extract-Direktive
    +
    +main.opt.include=\          --include      Musterliste für das Filtern von Einträgen.
    +
    +main.opt.full-version=\          --full-version               Gibt vollständige Versionsinformationen aus
    +
    +main.opt.help=\  -?, -h, --help                       Gibt diese Hilfemeldung aus
    +
    +main.opt.verbose=\          --verbose                    Gibt beim Auflisten die Eintragsgröße\n                                       und Offset-Attribute aus
    +
    +main.opt.version=\          --version                    Gibt Versionsinformationen aus
    +
    +main.command.files=\       @                  Liest Optionen aus der Datei
    +
    +main.opt.footer=\nBei Optionen, die eine  erfordern, ist der Wert eine durch Komma getrennte\nListe von Elementen, die jeweils eines der folgenden Formate verwenden:\n  \n  glob:\n  regex:
    +
    +
    +
    +err.not.a.task=Aufgabe muss einen der folgenden Werte aufweisen: : {0}
    +err.missing.arg=kein Wert angegeben für {0}
    +err.ambiguous.arg=Wert für Option {0} beginnt mit "--", aber muss das Format {0}= verwenden
    +err.not.a.dir=Kein Verzeichnis: {0}
    +err.not.a.jimage=Keine jimage-Datei: {0}
    +err.invalid.jimage={0} kann nicht geöffnet werden: {1}
    +err.no.jimage=Kein jimage angegeben
    +err.option.unsupported={0} nicht unterstützt: {1}
    +err.unknown.option=unbekannte Option: {0}
    +err.cannot.create.dir=Verzeichnis {0} kann nicht erstellt werden
    diff --git a/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_ja.properties
    new file mode 100644
    index 00000000000..66471e23b38
    --- /dev/null
    +++ b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_ja.properties
    @@ -0,0 +1,68 @@
    +#
    +# Copyright (c) 2015, 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.  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.
    +#
    +
    +main.usage.summary=使用方法: {0}   jimage...\n使用可能なオプションのリストについては、-hまたは--helpを使用します。
    +
    +main.usage=使用方法: {0}   jimage...\n\n  extract  - すべてのjimageエントリを抽出し、--dir= (default=''.'')\n             オプションで指定されたディレクトリに配置します。\n\n  info     - jimageヘッダーに含まれる詳細情報を出力します。\n\n  list     - jimage内のすべてのエントリの名前を出力します。--verboseと共に\n             使用すると、listはエントリ・サイズとオフセット属性も出力します。\n\n  verify   - クラスとして検証しない任意の.classエントリを報告します。\n\n使用可能なオプションには次のものがあります:
    +
    +main.usage.extract=\  extract  - すべてのjimageエントリを抽出し、--dir= (default='.')\n             オプションで指定されたディレクトリに配置します。
    +
    +main.usage.info=\  info     - jimageヘッダーに含まれる詳細情報を出力します。
    +
    +main.usage.list=\  list     - jimage内のすべてのエントリの名前を出力します。--verboseと共に\n             使用すると、listはエントリ・サイズとオフセット属性も出力します。
    +
    +main.usage.verify=\  verify   - クラスとして検証しない任意の.classエントリに関するエラーを報告します。
    +
    +error.prefix=エラー:
    +warn.prefix=警告:
    +
    +main.opt.dir=\          --dir                        抽出ディレクティブのターゲット・ディレクトリ
    +
    +main.opt.include=\          --include      フィルタリング・エントリのパターン・リスト。
    +
    +main.opt.full-version=\          --full-version               完全なバージョン情報を出力します
    +
    +main.opt.help=\  -?, -h, --help                       このヘルプ・メッセージを出力します
    +
    +main.opt.verbose=\          --verbose                    エントリ・サイズとオフセット属性の出力の\n                                       リスティング
    +
    +main.opt.version=\          --version                    バージョン情報を出力します
    +
    +main.command.files=\       @                  ファイルからオプションを読み取ります
    +
    +main.opt.footer=\nを必要とするオプションの場合、値は、次の形式のいずれかを使用する、\n要素のカンマ区切りリストになります:\n  \n  glob:\n  regex:
    +
    +
    +
    +err.not.a.task=タスクはのいずれかである必要があります: {0}
    +err.missing.arg={0}に値が指定されていません
    +err.ambiguous.arg=オプション{0}の値が"--"で始まっています。{0}=形式を使用する必要があります
    +err.not.a.dir=ディレクトリではありません: {0}
    +err.not.a.jimage=jimageファイルではありません: {0}
    +err.invalid.jimage={0}を開けません: {1}
    +err.no.jimage=jimageが提供されていません
    +err.option.unsupported={0}はサポートされていません: {1}
    +err.unknown.option=不明なオプション: {0}
    +err.cannot.create.dir=ディレクトリ{0}を作成できません
    diff --git a/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_zh_CN.properties
    new file mode 100644
    index 00000000000..8355ed5595e
    --- /dev/null
    +++ b/src/jdk.jlink/share/classes/jdk/tools/jimage/resources/jimage_zh_CN.properties
    @@ -0,0 +1,68 @@
    +#
    +# Copyright (c) 2015, 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.  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.
    +#
    +
    +main.usage.summary=用法:{0}   jimage...\n使用 -h 或 --help 列出可能的选项。
    +
    +main.usage=用法:{0}   jimage...\n\n  extract  - 提取所有 jimage 条目,并将其放置在\n             由 --dir= (default=''.'') 选项指定的目录中。\n\n  info     - 输出 jimage 标头中包含的详细信息。\n\n  list     - 输出 jimage 中所有条目的名称。与\n             --verbose 一起使用时,list 还将输出条目大小和偏移量属性。\n\n  verify   - 报告任何未验证为类的 .class 条目。\n\n可能的选项包括:
    +
    +main.usage.extract=\  extract  - 提取所有 jimage 条目,并将其放置在\n             由 --dir= (default='.') 选项指定的目录中。
    +
    +main.usage.info=\  info     - 输出 jimage 标头中包含的详细信息。
    +
    +main.usage.list=\  list     - 输出 jimage 中所有条目的名称。与 \n             --verbose 一起使用时,list 还将输出条目大小和偏移量属性。
    +
    +main.usage.verify=\  verify   - 报告任何未验证为类的 .class 条目的错误。
    +
    +error.prefix=错误:
    +warn.prefix=警告:
    +
    +main.opt.dir=\          --dir                        提取指令的目标目录
    +
    +main.opt.include=\          --include      用于筛选条目的模式列表。
    +
    +main.opt.full-version=\          --full-version               输出完整版本信息
    +
    +main.opt.help=\  -?, -h, --help                       输出此帮助消息
    +
    +main.opt.verbose=\          --verbose                    列表输出条目大小和偏移量\n                                       属性
    +
    +main.opt.version=\          --version                    输出版本信息
    +
    +main.command.files=\       @<文件名>                           从文件中读取选项
    +
    +main.opt.footer=\n对于需要  的选项,值将为逗号分隔的元素列表,\n每个元素使用以下格式之一:\n  \n  glob:\n  regex:
    +
    +
    +
    +err.not.a.task=任务必须是  之一:{0}
    +err.missing.arg=没有为{0}指定值
    +err.ambiguous.arg=选项 {0} 的值以 "--" 开头,应使用 {0}= 格式
    +err.not.a.dir=不是目录:{0}
    +err.not.a.jimage=不是 jimage 文件:{0}
    +err.invalid.jimage=无法打开 {0}: {1}
    +err.no.jimage=未提供 jimage
    +err.option.unsupported=不支持{0}: {1}
    +err.unknown.option=未知选项: {0}
    +err.cannot.create.dir=无法创建目录 {0}
    diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties
    index 6df60ada590..9b776745c66 100644
    --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties
    +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -61,7 +61,7 @@ main.msg.bug=Eine Ausnahme ist in jlink aufgetreten. Melden Sie in der Java-Bugd
     
     main.extended.help=Liste der verfügbaren Plug-ins:
     
    -main.extended.help.footer=Bei Optionen, die eine  erfordern, ist der Wert eine kommagetrennte\nListe von Elementen, die jeweils eines der folgenden Formate verwenden:\n  \n  glob:\n  regex:\n  @, wobei der Dateiname der Name einer Datei mit zu verwendenden Mustern ist,\n              ein Muster pro Zeile\n\n
    +main.extended.help.footer=Bei Optionen, die eine  erfordern, ist der Wert eine kommagetrennte\nListe von Elementen, die jeweils eines der folgenden Formate verwenden:\n  \n  glob:\n  regex:\n  @, wobei der Dateiname der Name einer Datei mit zu verwendenden Mustern ist,\n              ein Muster pro Zeile\n\n
     main.runtime.image.linking.cap.enabled=aktiviert
     main.runtime.image.linking.cap.disabled=deaktiviert
     main.runtime.image.linking.cap.sect.header=Funktionen:
    @@ -75,7 +75,7 @@ err.runtime.link.jdk.jlink.prohibited=Dieses JDK enthält keine verpackten Modul
     err.runtime.link.packaged.mods=Dieses JDK enthält keine verpackten Module. "--keep-packaged-modules" wird nicht unterstützt
     err.runtime.link.modified.file={0} wurde geändert
     err.runtime.link.patched.module=jlink unterstützt keine Verknüpfung vom Laufzeitimage unter einer gepatchten Laufzeit mit --patch-module
    -err.no.module.path=--module-path Option muss mit --add-modules ALL-MODULE-PATH angegeben werden
    +err.no.module.path=Option --module-path muss mit --add-modules ALL-MODULE-PATH angegeben werden
     err.empty.module.path=Kein Modul im Modulpfad "{0}" mit --add-modules ALL-MODULE-PATH gefunden
     err.limit.modules=--limit-modules nicht mit --add-modules ALL-MODULE-PATH zulässig
     err.jlink.version.mismatch=jlink-Version {0}.{1} stimmt nicht mit Ziel-java.base-Version {2}.{3} überein
    @@ -95,6 +95,7 @@ err.dir.exists={0} ist bereits vorhanden
     err.badpattern=ungültiges Muster {0}
     err.unknown.option=unbekannte Option: {0}
     err.missing.arg=kein Wert angegeben für {0}
    +err.ambiguous.arg=Wert für Option {0} beginnt mit "--", aber muss das Format {0}= verwenden
     err.internal.error=interner Fehler: {0} {1} {2}
     err.invalid.arg.for.option={0} akzeptiert nicht das Argument "{1}"
     err.option.after.class=Option muss angegeben werden vor den Klassen: {0}
    diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties
    index ef82d3bb461..c925f250c41 100644
    --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties
    +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -95,6 +95,7 @@ err.dir.exists={0}はすでに存在します
     err.badpattern=不正パターン{0}
     err.unknown.option=不明なオプション: {0}
     err.missing.arg={0}に値が指定されていません
    +err.ambiguous.arg=オプション{0}の値が"--"で始まっています。{0}=形式を使用する必要があります
     err.internal.error=内部エラー: {0} {1} {2}
     err.invalid.arg.for.option={0}は"{1}"引数を受け入れません
     err.option.after.class=オプションはクラスの前に指定する必要があります: {0}
    diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties
    index 12989131e65..b7526c9f57a 100644
    --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties
    +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -95,6 +95,7 @@ err.dir.exists={0} 已存在
     err.badpattern=错误的模式 {0}
     err.unknown.option=未知选项: {0}
     err.missing.arg=没有为{0}指定值
    +err.ambiguous.arg=选项 {0} 的值以 "--" 开头,应使用 {0}= 格式
     err.internal.error=内部错误: {0} {1} {2}
     err.invalid.arg.for.option={0} 不接受 "{1}" 参数
     err.option.after.class=必须在类之前指定选项: {0}
    diff --git a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_de.properties
    index a5896e94abb..126e04d0b58 100644
    --- a/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_de.properties
    +++ b/src/jdk.jlink/share/classes/jdk/tools/jmod/resources/jmod_de.properties
    @@ -47,7 +47,7 @@ main.opt.cmds=Speicherort der nativen Befehle
     main.opt.config=Speicherort der vom Benutzer editierbaren Konfigurationsdateien
     main.opt.extractDir=Zielverzeichnis für Extraktion
     main.opt.dry-run=Testlauf des Hashmodus
    -main.opt.exclude=Schließt Dateien aus, die der angegebenen kommagetrennten Musterliste entsprechen. Jedes Element verwendet eines der folgenden Formate: , glob: oder regex:
    +main.opt.exclude=Schließt Dateien aus, die der angegebenen kommagetrennten Musterliste entsprechen. Jedes Element verwendet eines der folgenden Formate: , glob: oder regex:
     main.opt.header-files=Speicherort der Headerdateien
     main.opt.legal-notices=Speicherort der rechtlichen Hinweise
     main.opt.module-version= Modulversion
    diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties
    index da983f76dd6..2f8fcddff73 100644
    --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties
    +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -44,10 +44,13 @@ resource.systemd-unit-file=systemd-Einheitsdatei
     error.tool-not-found.advice=Installieren Sie die erforderlichen Packages
     error.tool-old-version.advice=Installieren Sie die erforderlichen Packages
     
    -error.invalid-install-dir=Ungültiges Installationsverzeichnis "{0}"
    +error.deb-invalid-value-for-package-name=Ungültiger Wert "{0}" für den Packagenamen.
    +error.deb-invalid-value-for-package-name.advice=Setzen Sie die Option "--linux-package-name" auf einen gültigen Debian-Packagenamen. Die Packagenamen dürfen nur Kleinbuchstaben (a-z), Ziffern (0-9), Pluszeichen (+), Minuszeichen (-) und Punkte (.) umfassen. Sie müssen mindestens zwei Zeichen lang sein und mit einem Buchstaben beginnen.
     
    -error.invalid-value-for-package-name=Ungültiger Wert "{0}" für den Bundle-Namen.
    -error.invalid-value-for-package-name.advice=Setzen Sie die Option "linux-bundle-name" auf einen gültigen Debian-Packagenamen. Die Packagenamen dürfen nur Kleinbuchstaben (a-z), Ziffern (0-9), Pluszeichen (+), Minuszeichen (-) und Punkte (.) umfassen. Sie müssen mindestens zwei Zeichen lang sein und mit einem alphanumerischen Zeichen beginnen.
    +error.rpm-invalid-value-for-package-name=Ungültiger Wert "{0}" für den Packagenamen.
    +error.rpm-invalid-value-for-package-name.advice=Setzen Sie die Option "--linux-package-name" auf einen gültigen RPM-Packagenamen. Die Packagenamen dürfen nur Buchstaben (a-z, A-Z), Ziffern (0-9), Pluszeichen (+), Minuszeichen (-), Punkte (.) und Unterstriche (_) umfassen. Sie müssen mindestens ein Zeichen lang sein und mit einem Buchstaben beginnen.
    +
    +error.rpm-arch-not-detected="RPM-Architektur konnte nicht erkannt werden"
     
     message.icon-not-png=Das angegebene Symbol "{0}" ist keine PNG-Datei und wird nicht verwendet. Stattdessen wird das Standardsymbol verwendet.
     message.test-for-tool=Test für [{0}]. Ergebnis: {1}
    diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties
    index 002fc0baf48..be2cd00b42c 100644
    --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties
    +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -44,10 +44,13 @@ resource.systemd-unit-file=systemdユニット・ファイル
     error.tool-not-found.advice=必要なパッケージをインストールしてください
     error.tool-old-version.advice=必要なパッケージをインストールしてください
     
    -error.invalid-install-dir=無効なインストール・ディレクトリ"{0}"
    +error.deb-invalid-value-for-package-name=パッケージ名に対して値"{0}"は無効です。
    +error.deb-invalid-value-for-package-name.advice="--linux-package-name"オプションを有効なDebianパッケージ名に設定してください。パッケージ名には、小文字(a-z)、数字(0-9)、プラス(+)とマイナス(-)の記号およびピリオド(.)のみを含めるようにしてください。長さは2文字以上とし、文字で始める必要があります。
     
    -error.invalid-value-for-package-name=バンドル名の値"{0}"が無効です。
    -error.invalid-value-for-package-name.advice="linux-bundle-name"オプションを有効なDebianパッケージ名に設定してください。パッケージ名には、小文字(a-z)、数字(0-9)、プラス(+)とマイナス(-)の記号およびピリオド(.)のみを含めるようにしてください。長さは2文字以上とし、英数字で始める必要があります。
    +error.rpm-invalid-value-for-package-name=パッケージ名に対して値"{0}"は無効です。
    +error.rpm-invalid-value-for-package-name.advice="--linux-package-name"オプションを有効なRPMパッケージ名に設定してください。パッケージ名には、文字(a-z、A-Z)、数字(0-9)、プラス(+)とマイナス(-)の記号、ピリオド(.)およびアダースコア(_)のみを含めるようにしてください。長さは1文字以上とし、文字で始める必要があります。
    +
    +error.rpm-arch-not-detected="RPM archの検出に失敗しました"
     
     message.icon-not-png=指定したアイコン"{0}"はPNGファイルではなく、使用されません。デフォルト・アイコンがその位置に使用されます。
     message.test-for-tool=[{0}]のテスト。結果: {1}
    diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties
    index 034128f653a..5b583062ab6 100644
    --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties
    +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -44,10 +44,13 @@ resource.systemd-unit-file=systemd 单元文件
     error.tool-not-found.advice=请安装所需的程序包
     error.tool-old-version.advice=请安装所需的程序包
     
    -error.invalid-install-dir=安装目录 "{0}" 无效
    +error.deb-invalid-value-for-package-name=程序包名称的值 "{0}" 无效。
    +error.deb-invalid-value-for-package-name.advice=将 "--linux-package-name" 选项设置为有效的 Debian 程序包名称。请注意,程序包名称只能包含小写字母 (a-z)、数字 (0-9)、加号 (+) 和减号 (-) 以及句点 (.)。名称长度必须至少为两个字符并且必须以字母字符开头。
     
    -error.invalid-value-for-package-name=包名的值 "{0}" 无效。
    -error.invalid-value-for-package-name.advice=将 "linux-bundle-name" 选项设置为有效的 Debian 程序包名称。请注意,程序包名称只能包含小写字母 (a-z)、数字 (0-9)、加号 (+) 和减号 (-) 以及句点 (.)。名称长度必须至少为两个字符并且必须以字母数字字符开头。
    +error.rpm-invalid-value-for-package-name=程序包名称的值 "{0}" 无效。
    +error.rpm-invalid-value-for-package-name.advice=将 "--linux-package-name" 选项设置为有效的 RPM 程序包名称。请注意,程序包名称只能包含字母 (a-z, A-Z)、数字 (0-9)、加号 (+) 和减号 (-)、句点 (.) 以及下划线 (_)。名称长度必须至少为一个字符并且必须以字母开头。
    +
    +error.rpm-arch-not-detected="无法检测 RPM 体系结构"
     
     message.icon-not-png=指定的图标 "{0}" 不是 PNG 文件, 不会使用。将使用默认图标代替。
     message.test-for-tool=[{0}] 的测试。结果: {1}
    diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties
    index f76d3a3743f..7e36a260c3f 100644
    --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties
    +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -34,10 +34,6 @@ error.explicit-sign-no-cert=Signatur wurde explizit angefordert, doch es wurde k
     error.explicit-sign-no-cert.advice=Geben Sie gültige Werte für mac-signing-key-user-name und mac-signing-keychain an
     error.must-sign-app-store=Mac App Store-Apps müssen signiert werden. Die Signierung wurde von der Bundler-Konfiguration deaktiviert
     error.must-sign-app-store.advice=Verwenden Sie die Option --mac-sign mit entsprechenden Werten für user-name und keychain
    -error.no-app-signing-key=Kein Signaturschlüssel für Mac App Store-App
    -error.no-app-signing-key.advice=Installieren Sie Ihre App-Signaturschlüssel mit XCode in Ihrem Mac-Schlüsselbund.
    -error.no-pkg-signing-key=Kein Signaturschlüssel für Mac App Store-Installationsprogramm
    -error.no-pkg-signing-key.advice=Installieren Sie Ihre App-Signaturschlüssel mit XCode in Ihrem Mac-Schlüsselbund.
     error.certificate.expired=Fehler: Zertifikat abgelaufen {0}
     error.cert.not.found=Kein Zertifikat gefunden, das [{0}] mit Schlüsselbund [{1}] entspricht
     error.multiple.certs.found=WARNUNG: Mehrere Zertifikate gefunden, die [{0}] mit Schlüsselbund [{1}] entsprechen. Es wird das erste Zertifikat verwendet
    @@ -51,7 +47,6 @@ resource.dmg-setup-script=DMG-Setupskript
     resource.license-setup=Lizenzsetup
     resource.dmg-background=DMG-Hintergrund
     resource.volume-icon=Symbol "Datenträger"
    -resource.post-install-script=Auszuführendes Skript nach dem Auffüllen des Anwendungsimages
     resource.pkg-preinstall-script=PKG-Preinstall-Skript
     resource.pkg-postinstall-script=PKG-Postinstall-Skript
     resource.pkg-services-preinstall-script=PKG-Preinstall-Skript für Servicepackage
    @@ -72,12 +67,6 @@ message.ignoring.symlink=Warnung: codesign überspringt den Symlink {0}.
     message.already.signed=Datei ist bereits signiert: {0}.
     message.keychain.error=Fehler: Schlüsselbundliste kann nicht abgerufen werden.
     message.building-bundle=Mac App Store-Package für {0} wird erstellt.
    -message.app-image-dir-does-not-exist=Angegebenes Anwendungsimageverzeichnis {0}: {1} ist nicht vorhanden.
    -message.app-image-dir-does-not-exist.advice=Bestätigen Sie, dass der Wert für {0} vorhanden ist.
    -message.app-image-requires-app-name=Beim Verwenden eines internen Anwendungsimages müssen Sie den Anwendungsnamen angeben.
    -message.app-image-requires-app-name.advice=Legen Sie den Anwendungsnamen mit dem CLI-Kennzeichen -name, dem fx:application/@name ANT-Attribut oder dem Bundler-Argument "appName" fest.
    -message.app-image-requires-identifier=ID kann nicht aus Anwendungsimage extrahiert werden.
    -message.app-image-requires-identifier.advice=Verwenden Sie "--verbose" für eine erweiterte Fehlermeldung, oder geben Sie sie mit "--mac-package-identifier" an.
     message.invalid-identifier=Ungültige Mac-Bundle-ID [{0}].
     message.invalid-identifier.advice=Geben Sie die ID mit "--mac-package-identifier" an.
     message.building-dmg=DMG-Package für {0} wird erstellt.
    @@ -91,7 +80,6 @@ message.preparing-scripts=Packageskripte werden vorbereitet.
     message.preparing-distribution-dist=distribution.dist wird vorbereitet: {0}.
     message.signing.pkg=Warnung: Zum Signieren von PKG müssen Sie möglicherweise mit dem Schlüsselbundverwaltungstool die Option "Immer vertrauen" für Ihr Zertifikat festlegen.
     message.setfile.dmg=Das Festlegen des benutzerdefinierten Symbols für die DMG-Datei wurde übersprungen, weil das Utility "SetFile" nicht gefunden wurde. Durch Installieren von Xcode mit Befehlszeilentools sollte dieses Problem behoben werden.
    -message.install-dir-ignored=Warnung: "--install-dir" wird von DMG nicht unterstützt. Stattdessen wird standardmäßig /Applications verwendet.
     message.codesign.failed.reason.app.content="codesign" war nicht erfolgreich, und zusätzlicher Anwendungsinhalt wurde über den Parameter "--app-content" angegeben. Wahrscheinlich hat der zusätzliche Inhalt die Integrität des Anwendungs-Bundles beeinträchtigt und den Fehler verursacht. Stellen Sie sicher, das der über den Parameter "--app-content" angegebene Inhalt nicht die Integrität des Anwendungs-Bundles beeinträchtigt, oder fügen Sie ihn im Nachverarbeitungsschritt hinzu.
     message.codesign.failed.reason.xcode.tools=Möglicher Grund für "codesign"-Fehler ist fehlender Xcode mit Befehlszeilen-Entwicklertools. Installieren Sie Xcode mit Befehlszeilen-Entwicklertools, und prüfen Sie, ob das Problem dadurch beseitigt wird.
     warning.unsigned.app.image=Warnung: Nicht signiertes app-image wird zum Erstellen von signiertem {0} verwendet.
    diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties
    index 5ea13254e93..4384d6507f9 100644
    --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties
    +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -34,10 +34,6 @@ error.explicit-sign-no-cert=署名が明示的に要求されましたが、署
     error.explicit-sign-no-cert.advice=有効なmac-signing-key-user-nameおよびmac-signing-keychainを指定してください
     error.must-sign-app-store=Mac App Storeアプリケーションは署名されている必要がありますが、署名はバンドラ構成によって無効化されています
     error.must-sign-app-store.advice=--mac-signオプションを適切なuser-nameおよびkeychain付きで使用してください
    -error.no-app-signing-key=Mac App Storeアプリケーションの署名キーがありません
    -error.no-app-signing-key.advice=XCodeを使用してアプリケーションの署名キーをMacキーチェーンにインストールします。
    -error.no-pkg-signing-key=Mac App Storeインストーラの署名キーがありません
    -error.no-pkg-signing-key.advice=XCodeを使用してアプリケーションの署名キーをMacキーチェーンにインストールします。
     error.certificate.expired=エラー: 証明書は{0}に期限が切れました
     error.cert.not.found=キーチェーン[{1}]を使用する[{0}]と一致する証明書が見つかりません
     error.multiple.certs.found=警告: キーチェーン[{1}]を使用する[{0}]と一致する複数の証明書が見つかりました。最初のものを使用します
    @@ -51,7 +47,6 @@ resource.dmg-setup-script=DMG設定スクリプト
     resource.license-setup=ライセンスの設定
     resource.dmg-background=dmg背景
     resource.volume-icon=ボリューム・アイコン
    -resource.post-install-script=アプリケーション・イメージを移入した後に実行するスクリプト
     resource.pkg-preinstall-script=PKGインストール前スクリプト
     resource.pkg-postinstall-script=PKGインストール後スクリプト
     resource.pkg-services-preinstall-script=サービス・パッケージのPKGインストール前スクリプト
    @@ -72,12 +67,6 @@ message.ignoring.symlink=警告: codesignがsymlink {0}をスキップしてい
     message.already.signed=ファイルはすでに署名されています: {0}。
     message.keychain.error=エラー: キーチェーン・リストを取得できません。
     message.building-bundle={0}のMac App Storeパッケージを作成しています。
    -message.app-image-dir-does-not-exist=指定されたアプリケーション・イメージ・ディレクトリ {0}: {1}は存在しません。
    -message.app-image-dir-does-not-exist.advice={0}の値が存在することを確認してください
    -message.app-image-requires-app-name=外部アプリケーション・イメージを使用する場合、アプリケーション名を指定する必要があります。
    -message.app-image-requires-app-name.advice=-name CLIフラグ、fx:application/@name ANT属性または'appName'バンドラ引数でアプリケーション名を設定します。
    -message.app-image-requires-identifier=アプリケーション・イメージから識別子を抽出できません。
    -message.app-image-requires-identifier.advice=拡張エラー・メッセージに"--verbose"を使用するか、"--mac-package-identifier"を使用して指定します。
     message.invalid-identifier=macバンドル識別子[{0}]が無効です。
     message.invalid-identifier.advice="--mac-package-identifier"で識別子を指定してください。
     message.building-dmg={0}のDMGパッケージを作成しています
    @@ -91,7 +80,6 @@ message.preparing-scripts=パッケージ・スクリプトを準備していま
     message.preparing-distribution-dist=distribution.distを準備しています: {0}
     message.signing.pkg=警告: PKGへの署名の場合、「キーチェーン・アクセス」ツールを使用して証明書に「常に信頼する」を設定する必要があります。
     message.setfile.dmg='SetFile'ユーティリティが見つからないため、DMGファイルでのカスタム・アイコンの設定がスキップされました。Xcodeとコマンド・ライン・ツールをインストールすると、この問題は解決されます。
    -message.install-dir-ignored=警告: "--install-dir"はDMGでサポートされていません。/Applicationsにデフォルト設定されます。
     message.codesign.failed.reason.app.content="codesign"が失敗したため、追加のアプリケーション・コンテンツが、"--app-content"パラメータを介して提供されました。追加のコンテンツにより、アプリケーション・バンドルの整合性が損われ、失敗の原因になった可能性があります。"--app-content"パラメータを介して提供されたコンテンツによって、アプリケーション・バンドルの整合性が損われていないことを確認するか、処理後のステップで追加してください。
     message.codesign.failed.reason.xcode.tools="codesign"失敗の考えられる理由は、Xcodeとコマンドライン・デベロッパ・ツールの欠落です。Xcodeとコマンドライン・デベロッパ・ツールをインストールして、問題が解決されるかを確認してください。
     warning.unsigned.app.image=警告: 署名されていないapp-imageを使用して署名された{0}を作成します。
    diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties
    index 1a262f461ac..09c6d77694a 100644
    --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties
    +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -34,10 +34,6 @@ error.explicit-sign-no-cert=已明确请求签名,但找不到签名证书
     error.explicit-sign-no-cert.advice=指定有效的 mac-signing-key-user-name 和 mac-signing-keychain
     error.must-sign-app-store=Mac App Store 应用程序必须签名, 而打包程序配置已禁用签名
     error.must-sign-app-store.advice=将 --mac-sign 选项用于适当的用户名和密钥链
    -error.no-app-signing-key=无 Mac App Store 应用程序签名密钥
    -error.no-app-signing-key.advice=使用 XCode 将应用程序签名密钥安装到 Mac 密钥链中。
    -error.no-pkg-signing-key=无 Mac App Store 安装程序签名密钥
    -error.no-pkg-signing-key.advice=使用 XCode 将应用程序签名密钥安装到 Mac 密钥链中。
     error.certificate.expired=错误: 证书已失效 {0}
     error.cert.not.found=使用密钥链 [{1}] 找不到与 [{0}] 匹配的证书
     error.multiple.certs.found=警告:使用密钥链 [{1}] 找到多个与 [{0}] 匹配的证书,将使用第一个证书
    @@ -51,7 +47,6 @@ resource.dmg-setup-script=DMG 设置脚本
     resource.license-setup=许可证设置
     resource.dmg-background=DMG 背景
     resource.volume-icon=卷图标
    -resource.post-install-script=要在填充应用程序映像之后运行的脚本
     resource.pkg-preinstall-script=PKG 安装前脚本
     resource.pkg-postinstall-script=PKG 安装后脚本
     resource.pkg-services-preinstall-script=服务程序包的 PKG 安装前脚本
    @@ -72,12 +67,6 @@ message.ignoring.symlink=警告: codesign 正在跳过符号链接 {0}。
     message.already.signed=文件已签名:{0}。
     message.keychain.error=错误:无法获取密钥链列表。
     message.building-bundle=正在为 {0} 构建 Mac App Store 程序包。
    -message.app-image-dir-does-not-exist=指定的应用程序映像目录 {0}:{1} 不存在。
    -message.app-image-dir-does-not-exist.advice=确认 {0} 的值是否存在。
    -message.app-image-requires-app-name=使用外部应用程序映像时, 必须指定应用程序名称。
    -message.app-image-requires-app-name.advice=通过 -name CLI 标记, fx:application/@name ANT 属性或通过 'appName' 打包程序参数设置应用程序名称。
    -message.app-image-requires-identifier=无法从应用程序映像提取标识符。
    -message.app-image-requires-identifier.advice=请使用 "--verbose" 获取扩展错误消息,或者通过 "--mac-package-identifier" 指定它。
     message.invalid-identifier=无效的 Mac 包标识符 [{0}]。
     message.invalid-identifier.advice=请使用 "--mac-package-identifier" 指定标识符。
     message.building-dmg=正在为 {0} 构建 DMG 程序包。
    @@ -91,7 +80,6 @@ message.preparing-scripts=正在准备程序包脚本。
     message.preparing-distribution-dist=正在准备 distribution.dist: {0}。
     message.signing.pkg=警告:要对 PKG 进行签名,可能需要使用“密钥链访问”工具为证书设置“始终信任”。
     message.setfile.dmg=由于未找到 'SetFile' 实用程序,跳过了针对 DMG 文件设置定制图标的操作。安装带命令行工具的 Xcode 应能解决此问题。
    -message.install-dir-ignored=警告:"--install-dir" 不受 DMG 支持,将默认为 /Applications。
     message.codesign.failed.reason.app.content="codesign" 失败,并通过 "--app-content" 参数提供了附加应用程序内容。可能是附加内容破坏了应用程序包的完整性,导致了故障。请确保通过 "--app-content" 参数提供的内容不会破坏应用程序包的完整性,或者在后处理步骤中添加该内容。
     message.codesign.failed.reason.xcode.tools="codesign" 失败可能是因为缺少带命令行开发人员工具的 Xcode。请安装带命令行开发人员工具的 Xcode,看看是否可以解决问题。
     warning.unsigned.app.image=警告:使用未签名的 app-image 生成已签名的 {0}。
    diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties
    index 3c66e8bb151..c1cb5bf4283 100644
    --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties
    +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties
    @@ -33,7 +33,7 @@ MSG_Help_win_install=\  --win-dir-chooser\n          Fügt ein Dialogfeld hinzu,
     MSG_Help_win_install_dir=Relativer Unterpfad unter dem Standardinstallationsverzeichnis\n
     MSG_Help_mac_install=\  --mac-dmg-content [,...]\n          Nimmt den gesamten referenzierten Inhalt in die DMG-Datei auf.\n          Diese Option kann mehrmals verwendet werden. \n
     MSG_Help_mac_launcher=\  --mac-package-identifier \n          Eine ID, die die Anwendung für macOS eindeutig identifiziert\n          Standardwert ist der Hauptklassenname.\n          Es dürfen nur alphanumerische Zeichen (A-Z, a-z, 0-9), Bindestriche (-)\n          und Punkte (.) verwendet werden.\n  --mac-package-name \n          Name der Anwendung, wie in der Menüleiste angezeigt\n          Dieser kann vom Anwendungsnamen abweichen.\n          Er darf maximal 15 Zeichen enthalten und muss für die Anzeige\n          in der Menüleiste und im Infofenster der Anwendung geeignet sein.\n          Standardwert: Anwendungsname.\n  --mac-package-signing-prefix \n          Beim Signieren des Anwendungspackages wird dieser Wert\n          allen zu signierenden Komponenten ohne vorhandene\n          Package-ID als Präfix vorangestellt.\n  --mac-sign\n          Anforderung zum Signieren des Packages oder des vordefinierten\nAnwendungsimages\n  --mac-signing-keychain \n          Name des Schlüsselbundes für die Suche nach der Signaturidentität\n          Bei fehlender Angabe werden die Standardschlüsselbunde verwendet.\n  --mac-signing-key-user-name \n          Team- oder Benutzernamensteil der Apple-Signaturidentitäten. Um direkt zu steuern,\n          welche Signaturidentität zum Signieren eines Anwendungsimages oder\n          Installationsprogramms verwendet wird, verwenden Sie --mac-app-image-sign-identity und/oder\n          --mac-installer-sign-identity. Diese Option kann nicht mit\n          --mac-app-image-sign-identity oder --mac-installer-sign-identity kombiniert werden.\n  --mac-app-image-sign-identity \n          Zum Signieren des Anwendungsimages verwendete Identität. Dieser Wert wird\n          direkt an die Option --sign des Tools "codesign" übergeben. Diese Option kann nicht\n          mit --mac-signing-key-user-name kombiniert werden.\n  --mac-installer-sign-identity \n          Zum Signieren des Installationsprogramms "pkg" verwendete Identität. Dieser Wert wird\n          direkt an die Option --sign des Tools "productbuild" übergeben. Diese Option\n          kann nicht mit --mac-signing-key-user-name kombiniert werden.\n  --mac-app-store\n          Gibt an, dass die jpackage-Ausgabe für den\n          Mac App Store bestimmt ist.\n  --mac-entitlements \n          Pfad zu einer Datei mit Berechtigungen, die beim Signieren\n          von ausführbaren Dateien und Librarys im Bundle verwendet werden sollen.\n  --mac-app-category \n          Zeichenfolge für das Erstellen von LSApplicationCategoryType in\n          Anwendungs-plist. Standardwert: "utilities".\n
    -MSG_Help_linux_install=\  --linux-package-name \n          Name für das Linux-Package, Standardwert: Anwendungsname\n  --linux-deb-maintainer \n          Maintainer für .deb-Package\n  --linux-menu-group \n          Menügruppe, in der diese Anwendung abgelegt wird\n  --linux-package-deps \n          Erforderliche Packages oder Funktionen für die Anwendung\n  --linux-rpm-license-type \n          Typ der Lizenz ("License: " der RPM-SPEC-Datei)\n  --linux-app-release \n          Releasewert der RPM-SPEC-Datei  oder \n          Debian-Revisionswert der DEB-Kontrolldatei\n  --linux-app-category \n          Gruppenwert der RPM-SPEC-Datei  oder \n          Abschnittswert der DEB-Kontrolldatei\n  --linux-shortcut\n          Erstellt eine Verknüpfung für die Anwendung.\n
    +MSG_Help_linux_install=\  --linux-package-name \n          Name für das Linux-Package, Standardwert: Anwendungsname\n  --linux-deb-maintainer \n          Maintainer für .deb-Package\n  --linux-menu-group \n          Menügruppe, in der diese Anwendung abgelegt wird\n  --linux-package-deps \n          Erforderliche Packages oder Funktionen für die Anwendung\n  --linux-rpm-license-type \n          Typ der Lizenz ("License: " der RPM-SPEC-Datei)\n  --linux-app-release \n          Releasewert der RPM-Datei .spec oder \n          Debian-Revisionswert der DEB-Kontrolldatei\n  --linux-app-category \n          Gruppenwert der RPM-Datei .spec oder \n          Abschnittswert der DEB-Kontrolldatei\n  --linux-shortcut\n          Erstellt einen Shortcut für die Anwendung.\n
     MSG_Help_mac_linux_install_dir=Absoluter Pfad des Installationsverzeichnisses der Anwendung\n
     MSG_Help_default_install_dir=Absoluter Pfad des Installationsverzeichnisses der Anwendung auf OS X\n          oder Linux. Relativer Unterpfad des Installationsverzeichnisses der\n          Anwendung wie "Programme" oder "AppData" unter Windows.\n
     MSG_Help_no_args=Verwendung: jpackage \nVerwenden Sie jpackage --help (oder -h), um eine Liste möglicher Optionen aufzurufen
    diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties
    index e50af2320ce..1221ae747de 100644
    --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties
    +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -30,24 +30,23 @@ param.copyright.default=Copyright (C) {0,date,YYYY}
     param.description.default=Kein Wert
     param.vendor.default=Unbekannt
     
    +resource.post-app-image-script=Auszuführendes Skript nach dem Auffüllen des Anwendungsimages
    +
     message.using-default-resource=Standardpackageressource {0} {1} wird verwendet (durch Hinzufügen von {2} zu resource-dir ist eine Anpassung möglich).
     message.no-default-resource=Keine Standardpackageressource {0} {1} (durch Hinzufügen von {2} zu resource-dir ist eine Anpassung möglich).
     message.using-custom-resource-from-file=Benutzerdefinierte Packageressource {0} wird verwendet (aus Datei {1} geladen).
     message.using-custom-resource=Benutzerdefinierte Packageressource {0} wird verwendet (aus {1} geladen).
     message.creating-app-bundle=Anwendungspackage {0} wird in {1} erstellt
    -message.app-image-dir-does-not-exist=Angegebenes Anwendungsimageverzeichnis {0}: {1} ist nicht vorhanden
    -message.app-image-dir-does-not-exist.advice=Bestätigen Sie, dass der Wert für {0} vorhanden ist
     message.runtime-image-dir-does-not-exist=Angegebenes Laufzeitimageverzeichnis {0}: {1} ist nicht vorhanden
    -message.runtime-image-dir-does-not-exist.advice=Bestätigen Sie, dass der Wert für {0} vorhanden ist
     message.resource-dir-does-not-exist=Angegebenes Ressourcenverzeichnis {0}: {1} ist nicht vorhanden
     message.debug-working-directory=Arbeitsverzeichnis für Debug beibehalten: {0}
     message.bundle-created={0}-Package wurde erfolgreich erstellt
     message.module-version=Version "{0}" aus Modul "{1}" wird als Anwendungsversion verwendet
     message.module-class=Klasse "{0}" aus Modul "{1}" wird als Anwendungshauptklasse verwendet
     
    -error.version-string-empty="Version darf keine leere Zeichenfolge sein"
    -error.version-string-zero-length-component="Version [{0}] enthält eine Komponente mit einer Nulllänge"
    -error.version-string-invalid-component="Version [{0}] enthält ungültige Komponente [{1}]"
    +error.version-string-empty=Version darf keine leere Zeichenfolge sein
    +error.version-string-zero-length-component=Version [{0}] enthält eine Komponente mit Nulllänge
    +error.version-string-invalid-component=Version [{0}] enthält ungültige Komponente [{1}]
     
     error.cannot-create-output-dir=Zielverzeichnis {0} kann nicht erstellt werden
     error.cannot-write-to-output-dir=Zielverzeichnis {0} ist schreibgeschützt
    @@ -61,7 +60,6 @@ error.main-jar-does-not-exist.advice=Die Haupt-JAR-Datei muss relativ zum Eingab
     error.no-module-in-path="{0}-Modul im Modulpfad nicht gefunden"
     error.not-path-parameter="Ungültiger Wert für Parameter {0}: {1}"
     error.no-input-parameter="--input-Parameter für nicht modulare Anwendung fehlt"
    -error.no-main-jar-parameter="--main-jar-Parameter für nicht modulare Anwendung fehlt"
     
     error.no-content-types-for-file-association=Für Dateiverknüpfungsnummer {0} wurden keine MIME-Typen angegeben
     error.no-content-types-for-file-association.advice=Geben Sie einen MIME-Typ für Dateiverknüpfungsnummer {0} an
    @@ -75,11 +73,14 @@ error.tool-old-version.advice=Installieren Sie {0} {1} oder eine neuere Version
     error.jlink.failed=jlink nicht erfolgreich mit: {0}
     error.blocked.option=jlink-Option [{0}] ist in --jlink-options nicht zulässig
     error.no.name=Name nicht mit --name angegeben. Es kann auch kein Name aus app-image abgeleitet werden
    +error.no.name.advice=Geben Sie den Namen mit --name an
     
     warning.no.jdk.modules.found=Warnung: Keine JDK-Module gefunden
     
     error.foreign-app-image=Fehler : Fehlende .jpackage.xml-Datei in app-image-Verzeichnis "{0}"
    -error.invalid-app-image=Fehler: app-image-Verzeichnis "{0}" wurde von einer anderen jpackage-Version generiert, oder "{1}" ist nicht wohlgeformt
    +error.invalid-app-image=Fehler: app-image-Verzeichnis "{0}" wurde von einer anderen jpackage-Version generiert, oder Datei "{1}" ist nicht wohlgeformt
    +
    +error.invalid-install-dir=Ungültiges Installationsverzeichnis "{0}"
     
     MSG_BundlerFailed=Fehler: Bundler "{1}" ({0}) konnte kein Package generieren
     MSG_BundlerConfigException=Bundler {0} aufgrund eines Konfigurationsproblems übersprungen: {1} \nEmpfehlung zur Behebung: {2}
    @@ -96,11 +97,9 @@ ERR_InvalidOptionWithAppImageSigning=Fehler: Option [{0}] ist nicht gültig beim
     
     ERR_MissingArgument=Fehler: Fehlendes Argument: {0}
     ERR_MissingRequiredArgument=Fehler: Für das Argument {0} ist mindestens eines der folgenden Argumente erforderlich: [{1}]
    -ERR_MissingAppResources=Fehler: Keine Anwendungs-JAR-Dateien gefunden
     ERR_AppImageNotExist=Fehler: Anwendungsimageverzeichnis "{0}" ist nicht vorhanden
     ERR_NoAddLauncherName=Fehler: Für Option --add-launcher müssen ein Name und ein Dateipfad angegeben werden (--add-launcher =)
     ERR_NoUniqueName=Fehler: Für --add-launcher = ist ein eindeutiger Name erforderlich
    -ERR_NoJreInstallerName=Fehler: Für JRE-Installationsprogramme ist ein Namensparameter erforderlich
     ERR_InvalidAppName=Fehler: Ungültiger Anwendungsname: {0}
     ERR_InvalidSLName=Fehler: Ungültiger Name für hinzuzufügenden Launcher: {0}
     ERR_IconFileNotExit=Fehler: Die angegebene Symboldatei [{0}] ist nicht vorhanden
    @@ -110,8 +109,6 @@ ERR_InvalidOption=Fehler: Ungültige Option: [{0}]
     ERR_InvalidInstallerType=Fehler: Ungültiger oder nicht unterstützter Typ: [{0}]
     ERR_BothMainJarAndModule=Fehler: Die Optionen --main-jar und --module dürfen nicht beide vorhanden sein
     ERR_NoEntryPoint=Fehler: Für das Erstellen des Anwendungsimages muss entweder die Option --main-jar oder die Option --module angegeben werden
    -ERR_InputNotDirectory=Fehler: Das angegebene Eingabeverzeichnis ist kein Verzeichnis: {0}
    -ERR_CannotReadInputDir=Fehler: Keine Berechtigung zum Lesen aus Eingabeverzeichnis vorhanden: {0}
     ERR_CannotParseOptions=Fehler: Option @filename wird verarbeitet: {0}
     ERR_MissingJLinkOptMacAppStore=Fehler: Argument "--mac-app-store" erfordert eine {0}-Option für Argument "--jlink-options"
     ERR_MacAppStoreRuntimeBinExists=Fehler: Laufzeitimage "{0}" darf nicht den Ordner "bin" enthalten. Verwenden Sie die jlink-Option "--strip-native-commands" beim Generieren des Laufzeitimages mit dem Argument "--mac-app-store".
    diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties
    index c5f0dc328d2..5a04af8a7bc 100644
    --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties
    +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -30,24 +30,23 @@ param.copyright.default=Copyright (C) {0,date,YYYY}
     param.description.default=なし
     param.vendor.default=不明
     
    +resource.post-app-image-script=アプリケーション・イメージを移入した後に実行するスクリプト
    +
     message.using-default-resource=デフォルトのパッケージ・リソース{0} {1}の使用({2}をresource-dirに追加してカスタマイズ)。
     message.no-default-resource=デフォルトのパッケージ・リソース{0} {1}なし({2}をresource-dirに追加してカスタマイズ)。
     message.using-custom-resource-from-file=カスタム・パッケージ・リソース{0}の使用(ファイル{1}からロード済)
     message.using-custom-resource=カスタム・パッケージ・リソース{0}の使用({1}からロード済)
     message.creating-app-bundle=アプリケーション・パッケージを作成しています: {1}内の{0}
    -message.app-image-dir-does-not-exist=指定されたアプリケーション・イメージ・ディレクトリ{0}: {1}は存在しません
    -message.app-image-dir-does-not-exist.advice={0}の値が存在することを確認してください
     message.runtime-image-dir-does-not-exist=指定されたランタイム・イメージ・ディレクトリ{0}: {1}は存在しません
    -message.runtime-image-dir-does-not-exist.advice={0}の値が存在することを確認してください
     message.resource-dir-does-not-exist=指定されたリソース・ディレクトリ{0}: {1}は存在しません
     message.debug-working-directory=デバッグの作業ディレクトリが保持されました: {0}
     message.bundle-created={0}パッケージの作成に成功しました
     message.module-version=モジュール"{1}"のバージョン"{0}"をアプリケーション・バージョンとして使用
     message.module-class=モジュール"{1}"のクラス"{0}"をアプリケーション・メイン・クラスとして使用
     
    -error.version-string-empty="バージョンを空の文字列にすることはできません"
    -error.version-string-zero-length-component="バージョン[{0}]に長さゼロのコンポーネントが含まれます"
    -error.version-string-invalid-component="バージョン[{0}]に無効なコンポーネント[{1}]が含まれます"
    +error.version-string-empty=バージョンを空の文字列にすることはできません
    +error.version-string-zero-length-component=バージョン[{0}]に長さゼロのコンポーネントが含まれます
    +error.version-string-invalid-component=バージョン[{0}]に無効なコンポーネント[{1}]が含まれます
     
     error.cannot-create-output-dir=宛先ディレクトリ{0}を作成できません。
     error.cannot-write-to-output-dir=宛先ディレクトリ{0}は書込み不可です
    @@ -61,7 +60,6 @@ error.main-jar-does-not-exist.advice=入力ディレクトリに対して相対
     error.no-module-in-path="モジュール・パスに{0}モジュールが見つかりませんでした"
     error.not-path-parameter="{0}パラメータの無効な値: {1}"
     error.no-input-parameter="非モジュラ・アプリケーションに--inputパラメータがありません"
    -error.no-main-jar-parameter="非モジュラ・アプリケーションに--main-jarパラメータがありません"
     
     error.no-content-types-for-file-association=ファイル・アソシエーション番号{0}にMIMEタイプが指定されませんでした
     error.no-content-types-for-file-association.advice=ファイル・アソシエーション番号{0}にMIMEタイプを指定してください
    @@ -75,11 +73,14 @@ error.tool-old-version.advice={0} {1}以降をインストールしてくださ
     error.jlink.failed=jlinkが次で失敗しました: {0}
     error.blocked.option=jlinkオプション[{0}]は--jlink-optionsでは許可されません
     error.no.name=名前が--nameで指定されておらず、app-imageから推論できません
    +error.no.name.advice=--nameで名前を指定します
     
     warning.no.jdk.modules.found=警告: JDKモジュールが見つかりません
     
     error.foreign-app-image=エラー: app-imageディレクトリ"{0}"に.jpackage.xmlファイルがありません
    -error.invalid-app-image=エラー: app-imageディレクトリ"{0}"は、別のjpackageバージョンまたは不正な"{1}"で生成されました
    +error.invalid-app-image=エラー: app-imageディレクトリ"{0}"は、別のjpackageバージョンまたは不正な"{1}"ファイルで生成されました
    +
    +error.invalid-install-dir=無効なインストール・ディレクトリ"{0}"
     
     MSG_BundlerFailed=エラー: バンドラ"{1}" ({0})がパッケージの生成に失敗しました
     MSG_BundlerConfigException=構成の問題のため、バンドラ{0}がスキップされました: {1} \n次の修正を行ってください: {2}
    @@ -96,11 +97,9 @@ ERR_InvalidOptionWithAppImageSigning=エラー: アプリケーション・イ
     
     ERR_MissingArgument=エラー: 引数がありません: {0}
     ERR_MissingRequiredArgument=エラー: {0}引数には少なくとも1つの[{1}]引数が必要です
    -ERR_MissingAppResources=エラー: アプリケーションjarが見つかりませんでした
     ERR_AppImageNotExist=エラー: アプリケーション・イメージ・ディレクトリ"{0}"は存在しません
     ERR_NoAddLauncherName=エラー: --add-launcherオプションには名前およびファイル・パスが必要です(--add-launcher =)
     ERR_NoUniqueName=エラー: --add-launcher =には一意の名前が必要です
    -ERR_NoJreInstallerName=エラー: Jreインストーラには名前パラメータが必要です
     ERR_InvalidAppName=エラー: 無効なアプリケーション名: {0}
     ERR_InvalidSLName=エラー: 無効な追加ランチャ名: {0}
     ERR_IconFileNotExit=エラー: 指定されたアイコン・ファイル[{0}]は存在しません
    @@ -110,8 +109,6 @@ ERR_InvalidOption=エラー: 無効なオプション: [{0}]
     ERR_InvalidInstallerType=エラー: 無効またはサポートされていないタイプ: [{0}]
     ERR_BothMainJarAndModule=エラー: --main-jarオプションと--moduleオプションの両方を指定することはできません
     ERR_NoEntryPoint=エラー: アプリケーション・イメージの作成には--main-jarまたは--moduleオプションが必要です
    -ERR_InputNotDirectory=エラー: 指定された入力ディレクトリはディレクトリではありません: {0}
    -ERR_CannotReadInputDir=エラー: 入力ディレクトリから読み取る権限がありません: {0}
     ERR_CannotParseOptions=エラー: @filenameオプションの処理: {0}
     ERR_MissingJLinkOptMacAppStore=エラー: --mac-app-store引数では、--jlink-options引数に{0}オプションが必要です
     ERR_MacAppStoreRuntimeBinExists=エラー: ランタイム・イメージ"{0}"に"bin"フォルダを含めることはできません。--mac-app-store引数で使用されるランタイム・イメージを生成する際に、--strip-native-commands jlinkオプションを使用します。
    diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties
    index 0d9c3b5a676..5546abef09f 100644
    --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties
    +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -30,24 +30,23 @@ param.copyright.default=版权所有 (C) {0,date,YYYY}
     param.description.default=无
     param.vendor.default=未知
     
    +resource.post-app-image-script=要在填充应用程序映像之后运行的脚本
    +
     message.using-default-resource=使用默认程序包资源 {0} {1}(将 {2} 添加到 resource-dir 中以进行定制)。
     message.no-default-resource=无默认程序包资源 {0} {1}(将 {2} 添加到 resource-dir 中以进行定制)。
     message.using-custom-resource-from-file=使用定制程序包资源 {0} (从文件 {1} 加载)。
     message.using-custom-resource=使用定制程序包资源 {0} (从 {1} 加载)。
     message.creating-app-bundle=正在 {1} 中创建应用程序包 {0}
    -message.app-image-dir-does-not-exist=指定的应用程序映像目录 {0}:{1} 不存在
    -message.app-image-dir-does-not-exist.advice=确认 {0} 的值是否存在
     message.runtime-image-dir-does-not-exist=指定的运行时映像目录 {0}:{1} 不存在
    -message.runtime-image-dir-does-not-exist.advice=确认 {0} 的值是否存在
     message.resource-dir-does-not-exist=指定的资源目录 {0}:{1} 不存在
     message.debug-working-directory=用于调试的已保留工作目录: {0}
     message.bundle-created=已成功地构建 {0} 程序包
     message.module-version=正在将模块 "{1}" 中的版本 "{0}" 用作应用程序版本
     message.module-class=正在将模块 "{1}" 中的类 "{0}" 用作应用程序主类
     
    -error.version-string-empty="版本不能为空字符串"
    -error.version-string-zero-length-component="版本 [{0}] 包含长度为零的组件"
    -error.version-string-invalid-component="版本 [{0}] 包含无效组件 [{1}]"
    +error.version-string-empty=版本不能为空字符串
    +error.version-string-zero-length-component=版本 [{0}] 包含长度为零的组件
    +error.version-string-invalid-component=版本 [{0}] 包含无效组件 [{1}]
     
     error.cannot-create-output-dir=无法创建目标目录 {0}
     error.cannot-write-to-output-dir=目标目录 {0} 不可写
    @@ -61,7 +60,6 @@ error.main-jar-does-not-exist.advice=必须使用相对于输入目录的路径
     error.no-module-in-path="无法在模块路径中找到 {0} 模块"
     error.not-path-parameter="{0} 参数的值无效:{1}"
     error.no-input-parameter="非模块化应用程序缺少 --input 参数"
    -error.no-main-jar-parameter="非模块化应用程序缺少 --main-jar 参数"
     
     error.no-content-types-for-file-association=没有为文件关联号{0}指定 MIME 类型
     error.no-content-types-for-file-association.advice=为文件关联号 {0} 指定 MIME 类型
    @@ -75,11 +73,14 @@ error.tool-old-version.advice=请安装 {0} {1}或更新版本
     error.jlink.failed=jlink 失败,出现 {0}
     error.blocked.option=不允许在 --jlink-options 中使用 jlink 选项 [{0}]
     error.no.name=未使用 --name 指定名称,无法从 app-image 推断名称
    +error.no.name.advice=使用 --name 指定名称
     
     warning.no.jdk.modules.found=警告: 未找到 JDK 模块
     
     error.foreign-app-image=错误:app-image 目录 "{0}" 中缺少 .jpackage.xml 文件
    -error.invalid-app-image=错误:另一个 jpackage 版本或格式错误的 "{1}" 生成了 app-image 目录 "{0}"
    +error.invalid-app-image=错误:另一个 jpackage 版本或格式错误的 "{1}" 文件生成了 app-image 目录 "{0}"
    +
    +error.invalid-install-dir=安装目录 "{0}" 无效
     
     MSG_BundlerFailed=错误:打包程序 "{1}" ({0}) 无法生成程序包
     MSG_BundlerConfigException=由于配置问题, 跳过了打包程序{0}: {1} \n修复建议: {2}
    @@ -96,11 +97,9 @@ ERR_InvalidOptionWithAppImageSigning=错误:对应用程序映像签名时,
     
     ERR_MissingArgument=错误: 缺少参数: {0}
     ERR_MissingRequiredArgument=错误:{0} 参数至少需要 [{1}] 参数之一
    -ERR_MissingAppResources=错误: 找不到应用程序 jar
     ERR_AppImageNotExist=错误:应用程序映像目录 "{0}" 不存在
     ERR_NoAddLauncherName=错误:--add-launcher 选项需要一个名称和一个文件路径 (--add-launcher =)
     ERR_NoUniqueName=错误:--add-launcher = 需要一个唯一的名称
    -ERR_NoJreInstallerName=错误:Jre 安装程序需要一个名称参数
     ERR_InvalidAppName=错误:应用程序名称 {0} 无效
     ERR_InvalidSLName=错误:添加启动程序名称 {0} 无效
     ERR_IconFileNotExit=错误:指定的图标文件 [{0}] 不存在
    @@ -110,8 +109,6 @@ ERR_InvalidOption=错误:选项 [{0}] 无效
     ERR_InvalidInstallerType=错误:类型 [{0}] 无效或不受支持
     ERR_BothMainJarAndModule=错误:不能同时包含 --main-jar 和 --module 选项
     ERR_NoEntryPoint=错误:创建应用程序映像需要 --main-jar 或 --module 选项
    -ERR_InputNotDirectory=错误:指定的输入目录不是目录:{0}
    -ERR_CannotReadInputDir=错误:无权从输入目录读取:{0}
     ERR_CannotParseOptions=错误:正在处理 @filename 选项:{0}
     ERR_MissingJLinkOptMacAppStore=错误:对于 --jlink-options 参数,--mac-app-store 参数需要 {0} 选项
     ERR_MacAppStoreRuntimeBinExists=错误:运行时映像 "{0}" 不应包含 "bin" 文件夹。生成与 --mac-app-store 参数一起使用的运行时映像时,使用 --strip-native-commands jlink 选项。
    diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl
    index 5e30d3744ec..2d0d1d098f8 100644
    --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl
    +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_de.wxl
    @@ -16,5 +16,5 @@
     
       Mit [ProductName] öffnen
     
    -  [ProductName][ProductVersion] is not supported on this version of Windows
    +  [ProductName][ProductVersion] wird unter dieser Windows-Version nicht unterstützt
     
    diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl
    index 4639e2f8fed..88a662b4b1f 100644
    --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl
    +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_ja.wxl
    @@ -16,5 +16,5 @@
     
       [ProductName]で開く
     
    -  [ProductName][ProductVersion] is not supported on this version of Windows
    +  [ProductName][ProductVersion]は、 このバージョンのWindowsでサポートされていません
     
    diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl
    index 06974dd84e5..48a342e58a3 100644
    --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl
    +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/MsiInstallerStrings_zh_CN.wxl
    @@ -16,5 +16,5 @@
     
       使用 [ProductName] 打开
     
    -  [ProductName][ProductVersion] is not supported on this version of Windows
    +  此版本的 Windows 不支持 [ProductName][ProductVersion]
     
    diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties
    index b6561747ce0..3e6f8e30d6a 100644
    --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties
    +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -32,7 +32,6 @@ param.menu-group.default=Unbekannt
     
     resource.executable-properties-template=Vorlage für das Erstellen der ausführbaren Eigenschaftendatei
     resource.setup-icon=Symbol für Dialogfeld "Setup"
    -resource.post-app-image-script=Auszuführendes Skript nach dem Auffüllen des Anwendungsimages
     resource.post-msi-script=Auszuführendes Skript nach dem Erstellen der MSI-Datei für das EXE-Installationsprogramm
     resource.wxl-file=WiX-Lokalisierungsdatei
     resource.main-wix-file=Haupt-WiX-Projektdatei
    @@ -41,6 +40,7 @@ resource.shortcutpromptdlg-wix-file=Dialogfeld für Verknüpfungs-Prompt der WiX
     resource.installdirnotemptydlg-wix-file=Nicht leeres Installationsverzeichnis in Dialogfeld für WiX-Projektdatei
     resource.launcher-as-service-wix-file=WiX-Projektdatei für Serviceinstallationsprogramm
     resource.wix-src-conv=XSLT-Stylesheet zum Konvertieren von WiX-Quellen vom Format WiX v3 in WiX v4
    +resource.installer-exe=Ausführbares Installationsprogramm
     
     error.no-wix-tools=WiX-Tools nicht gefunden. Gesucht wurden WiX v3 light.exe und candle.exe oder WiX v4/v5 wix.exe, aber keine der Dateien wurde gefunden
     error.no-wix-tools.advice=Laden Sie WiX 3.0 oder höher von https://wixtoolset.org herunter, und fügen Sie es zu PATH hinzu.
    @@ -67,7 +67,6 @@ message.output-location=Installationsprogramm (.exe) gespeichert in: {0}
     message.tool-version=[{0}]-Version [{1}] erkannt.
     message.creating-association-with-null-extension=Verknüpfung mit Nullerweiterung wird erstellt.
     message.wrong-tool-version=[{0}]-Version {1} wurde erkannt. Erforderlich ist jedoch Version {2}.
    -message.version-string-too-many-components=Versionszeichenfolge kann bis zu 3 Komponenten aufweisen: major.minor.build.
     message.use-wix36-features=WiX {0} erkannt. Erweiterte Bereinigungsaktion wird aktiviert.
     message.product-code=MSI-ProductCode: {0}.
     message.upgrade-code=MSI-UpgradeCode: {0}.
    diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties
    index 5dbf0eaa058..07604dc9980 100644
    --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties
    +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -32,7 +32,6 @@ param.menu-group.default=不明
     
     resource.executable-properties-template=実行可能なプロパティ・ファイル作成用のテンプレート
     resource.setup-icon=設定ダイアログ・アイコン
    -resource.post-app-image-script=アプリケーション・イメージを移入した後に実行するスクリプト
     resource.post-msi-script=exeインストーラのmsiファイルが作成された後に実行するスクリプト
     resource.wxl-file=WiXローカリゼーション・ファイル
     resource.main-wix-file=メインWiXプロジェクト・ファイル
    @@ -41,6 +40,7 @@ resource.shortcutpromptdlg-wix-file=ショートカット・プロンプト・
     resource.installdirnotemptydlg-wix-file=インストール・ディレクトリ・ダイアログのWiXプロジェクト・ファイルが空ではありません
     resource.launcher-as-service-wix-file=サービス・インストーラWiXプロジェクト・ファイル
     resource.wix-src-conv=WiXソースをWiX v3からWiX v4フォーマットに変換するXSLTスタイルシート
    +resource.installer-exe=インストーラ実行可能ファイル
     
     error.no-wix-tools=WiXツールが見つかりません。WiX v3 light.exeとcandle.exeまたはWiX v4/v5 wix.exeを探しましたが、いずれも見つかりませんでした
     error.no-wix-tools.advice=WiX 3.0以降をhttps://wixtoolset.orgからダウンロードし、PATHに追加します。
    @@ -67,7 +67,6 @@ message.output-location=インストーラ(.exe)は次に保存されました:
     message.tool-version=[{0}]バージョン[{1}]が検出されました。
     message.creating-association-with-null-extension=null拡張子との関連付けを作成しています。
     message.wrong-tool-version=[{0}]バージョン{1}が検出されましたが、バージョン{2}が必要です。
    -message.version-string-too-many-components=バージョン文字列には、コンポーネントを3つ(メジャー.マイナー.ビルド)まで含めることができます。
     message.use-wix36-features=WiX {0}が検出されました。拡張クリーンアップ・アクションを有効化しています。
     message.product-code=MSI ProductCode: {0}。
     message.upgrade-code=MSI UpgradeCode: {0}。
    diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties
    index 2fb4e8e40e7..7eae69fba2f 100644
    --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties
    +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties
    @@ -1,5 +1,5 @@
     #
    -# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
    +# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
     # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     #
     # This code is free software; you can redistribute it and/or modify it
    @@ -32,7 +32,6 @@ param.menu-group.default=未知
     
     resource.executable-properties-template=用于创建可执行属性文件的模板
     resource.setup-icon=设置对话框图标
    -resource.post-app-image-script=要在填充应用程序映像之后运行的脚本
     resource.post-msi-script=在为 exe 安装程序创建 msi 文件之后要运行的脚本
     resource.wxl-file=WiX 本地化文件
     resource.main-wix-file=主 WiX 项目文件
    @@ -41,6 +40,7 @@ resource.shortcutpromptdlg-wix-file=快捷方式提示对话框 WiX 项目文件
     resource.installdirnotemptydlg-wix-file=安装目录对话框 WiX 项目文件非空
     resource.launcher-as-service-wix-file=服务安装程序 WiX 项目文件
     resource.wix-src-conv=将 WiX 源码从 WiX v3 格式转换为 WiX v4 格式的 XSLT 样式表
    +resource.installer-exe=安装程序可执行文件
     
     error.no-wix-tools=找不到 WiX 工具。已查找 WiX v3 light.exe 和 candle.exe 或 WiX v4/v5 wix.exe,但都未找到
     error.no-wix-tools.advice=从 https://wixtoolset.org 下载 WiX 3.0 或更高版本,然后将其添加到 PATH。
    @@ -67,7 +67,6 @@ message.output-location=安装程序 (.exe) 已保存到: {0}
     message.tool-version=检测到 [{0}] 版本 [{1}]。
     message.creating-association-with-null-extension=正在使用空扩展名创建关联。
     message.wrong-tool-version=检测到 [{0}] 版本 {1}, 但需要版本 {2}。
    -message.version-string-too-many-components=版本字符串最多可以具有 3 个组成部分 - major.minor.build。
     message.use-wix36-features=检测到 WiX {0}。正在启用高级清除操作。
     message.product-code=MSI ProductCode:{0}。
     message.upgrade-code=MSI UpgradeCode:{0}。
    diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties
    index dbd4a5183c3..cb93ae4ed57 100644
    --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties
    +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_de.properties
    @@ -154,6 +154,7 @@ jshell.err.exception.thrown = Ausnahme {0}
     jshell.err.exception.thrown.message = Ausnahme {0}: {1}
     jshell.err.exception.cause = Verursacht von: {0}
     jshell.err.exception.cause.message = Verursacht von: {0}: {1}
    +jshell.err.incomplete.input = Unvollständige Eingabe: {0}
     
     jshell.console.see.synopsis = 
     jshell.console.see.full.documentation = 
    diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties
    index 14a88c56b70..fa84c3f38fb 100644
    --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties
    +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_ja.properties
    @@ -154,6 +154,7 @@ jshell.err.exception.thrown = 例外{0}
     jshell.err.exception.thrown.message = 例外{0}: {1}
     jshell.err.exception.cause = 原因: {0}
     jshell.err.exception.cause.message = 原因: {0}: {1}
    +jshell.err.incomplete.input = 不完全な入力: {0}
     
     jshell.console.see.synopsis = <概要を表示するにはタブを再度押してください>
     jshell.console.see.full.documentation = <ドキュメント全体を表示するにはタブを再度押してください>
    diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_zh_CN.properties b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_zh_CN.properties
    index 0bbc5d76404..879e9633e6a 100644
    --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_zh_CN.properties
    +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/resources/l10n_zh_CN.properties
    @@ -154,6 +154,7 @@ jshell.err.exception.thrown = 异常错误 {0}
     jshell.err.exception.thrown.message = 异常错误 {0}:{1}
     jshell.err.exception.cause = 原因:{0}
     jshell.err.exception.cause.message = 原因: {0}: {1}
    +jshell.err.incomplete.input = 输入不完整:{0}
     
     jshell.console.see.synopsis = <再次按 Tab 可查看提要>
     jshell.console.see.full.documentation = <再次按 Tab 可查看完整文档>
    
    From 712d866b72b43c839c57c3303dfb215f94c0db3b Mon Sep 17 00:00:00 2001
    From: Chris Plummer 
    Date: Fri, 27 Jun 2025 17:19:22 +0000
    Subject: [PATCH 211/213] 8360312: Serviceability Agent tests fail with JFR
     enabled due to unknown thread type JfrRecorderThread
    
    Reviewed-by: sspitsyn, kevinw, dholmes
    ---
     .../share/jfr/recorder/service/jfrRecorderThread.cpp   |  8 --------
     .../share/jfr/recorder/service/jfrRecorderThread.hpp   | 10 +++++++++-
     src/hotspot/share/runtime/vmStructs.cpp                |  2 ++
     .../share/classes/sun/jvm/hotspot/runtime/Threads.java |  4 +++-
     .../sa/ClhsdbJstackWithConcurrentLock.java             |  4 ++--
     5 files changed, 16 insertions(+), 12 deletions(-)
    
    diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp
    index 71b7014e6ec..aa594ea6d1f 100644
    --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp
    +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.cpp
    @@ -36,14 +36,6 @@
     #include "utilities/preserveException.hpp"
     #include "utilities/macros.hpp"
     
    -class JfrRecorderThread : public JavaThread {
    - public:
    -  JfrRecorderThread(ThreadFunction entry_point) : JavaThread(entry_point) {}
    -  virtual ~JfrRecorderThread() {}
    -
    -  virtual bool is_JfrRecorder_thread() const { return true; }
    -};
    -
     static Thread* start_thread(instanceHandle thread_oop, ThreadFunction proc, TRAPS) {
       assert(thread_oop.not_null(), "invariant");
       assert(proc != nullptr, "invariant");
    diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp
    index df8b1f55a4e..34993e4e6cf 100644
    --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp
    +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderThread.hpp
    @@ -26,9 +26,9 @@
     #define SHARE_JFR_RECORDER_SERVICE_JFRRECORDERTHREAD_HPP
     
     #include "memory/allStatic.hpp"
    +#include "runtime/javaThread.hpp"
     #include "utilities/debug.hpp"
     
    -class JavaThread;
     class JfrCheckpointManager;
     class JfrPostBox;
     class Thread;
    @@ -42,4 +42,12 @@ class JfrRecorderThreadEntry : AllStatic {
       static bool start(JfrCheckpointManager* cp_manager, JfrPostBox* post_box, TRAPS);
     };
     
    +class JfrRecorderThread : public JavaThread {
    + public:
    +  JfrRecorderThread(ThreadFunction entry_point) : JavaThread(entry_point) {}
    +  virtual ~JfrRecorderThread() {}
    +
    +  virtual bool is_JfrRecorder_thread() const { return true; }
    +};
    +
     #endif // SHARE_JFR_RECORDER_SERVICE_JFRRECORDERTHREAD_HPP
    diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp
    index e248e0f05be..71cba9ec085 100644
    --- a/src/hotspot/share/runtime/vmStructs.cpp
    +++ b/src/hotspot/share/runtime/vmStructs.cpp
    @@ -44,6 +44,7 @@
     #include "gc/shared/vmStructs_gc.hpp"
     #include "interpreter/bytecodes.hpp"
     #include "interpreter/interpreter.hpp"
    +#include "jfr/recorder/service/jfrRecorderThread.hpp"
     #include "logging/logAsyncWriter.hpp"
     #include "memory/allocation.hpp"
     #include "memory/allocation.inline.hpp"
    @@ -1027,6 +1028,7 @@
             declare_type(TrainingReplayThread, JavaThread)                    \
             declare_type(StringDedupThread, JavaThread)                       \
             declare_type(AttachListenerThread, JavaThread)                    \
    +        declare_type(JfrRecorderThread, JavaThread)                       \
             DEBUG_ONLY(COMPILER2_OR_JVMCI_PRESENT(                            \
               declare_type(DeoptimizeObjectsALotThread, JavaThread)))         \
       declare_toplevel_type(OSThread)                                         \
    diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java
    index 1230bea184c..6acacc28722 100644
    --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java
    +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Threads.java
    @@ -158,6 +158,7 @@ private static synchronized void initialize(TypeDataBase db) {
             virtualConstructor.addMapping("JvmtiAgentThread", JavaThread.class);
             virtualConstructor.addMapping("NotificationThread", JavaThread.class);
             virtualConstructor.addMapping("AttachListenerThread", JavaThread.class);
    +        virtualConstructor.addMapping("JfrRecorderThread", JavaThread.class);
     
             // These are all the hidden JavaThread subclasses that don't execute java code.
             virtualConstructor.addMapping("StringDedupThread", HiddenJavaThread.class);
    @@ -195,7 +196,8 @@ public JavaThread createJavaThreadWrapper(Address threadAddr) {
             } catch (Exception e) {
                 throw new RuntimeException("Unable to deduce type of thread from address " + threadAddr +
                 " (expected type JavaThread, CompilerThread, MonitorDeflationThread, AttachListenerThread," +
    -            " DeoptimizeObjectsALotThread, StringDedupThread, NotificationThread, ServiceThread or JvmtiAgentThread)", e);
    +            " DeoptimizeObjectsALotThread, StringDedupThread, NotificationThread, ServiceThread," +
    +            " JfrRecorderThread, or JvmtiAgentThread)", e);
             }
         }
     
    diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java
    index 43926941a1a..64080b252c5 100644
    --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java
    +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbJstackWithConcurrentLock.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -46,7 +46,7 @@ public static void main(String[] args) throws Exception {
     
                 theApp = new LingeredAppWithConcurrentLock();
                 // Use a small heap so the scan is quick.
    -            LingeredApp.startApp(theApp, "-Xmx4m");
    +            LingeredApp.startApp(theApp, "-Xmx8m");
                 System.out.println("Started LingeredApp with pid " + theApp.getPid());
     
                 // Run the 'jstack -l' command to get the stack and have java.util.concurrent
    
    From 3525a40f39a966b8592f694a9b3cd4c5dc449266 Mon Sep 17 00:00:00 2001
    From: Archie Cobbs 
    Date: Fri, 27 Jun 2025 18:25:27 +0000
    Subject: [PATCH 212/213] 8359596: Behavior change when both -Xlint:options and
     -Xlint:-options flags are given
    
    Reviewed-by: mcimadamore, uschindler
    ---
     .../com/sun/tools/javac/code/Lint.java        |  4 +-
     .../com/sun/tools/javac/comp/Modules.java     |  2 +-
     .../com/sun/tools/javac/main/Arguments.java   |  4 +-
     .../com/sun/tools/javac/util/Options.java     | 72 +++++++++++--------
     .../tools/javac/lint/LintOptions.java         | 38 ++++++++++
     .../tools/javac/lint/LintOptions.out          |  4 ++
     6 files changed, 89 insertions(+), 35 deletions(-)
     create mode 100644 test/langtools/tools/javac/lint/LintOptions.java
     create mode 100644 test/langtools/tools/javac/lint/LintOptions.out
    
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
    index ede2511f35c..2ed365bcbfa 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java
    @@ -183,9 +183,9 @@ private void initializeRootIfNeeded() {
     
             // Look for specific overrides
             for (LintCategory lc : LintCategory.values()) {
    -            if (options.isExplicitlyEnabled(Option.XLINT, lc)) {
    +            if (options.isLintExplicitlyEnabled(lc)) {
                     values.add(lc);
    -            } else if (options.isExplicitlyDisabled(Option.XLINT, lc)) {
    +            } else if (options.isLintExplicitlyDisabled(lc)) {
                     values.remove(lc);
                 }
             }
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
    index a159793fe32..47066b24de9 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Modules.java
    @@ -205,7 +205,7 @@ protected Modules(Context context) {
     
             allowAccessIntoSystem = options.isUnset(Option.RELEASE);
     
    -        lintOptions = !options.isExplicitlyDisabled(Option.XLINT, LintCategory.OPTIONS);
    +        lintOptions = !options.isLintDisabled(LintCategory.OPTIONS);
     
             multiModuleMode = fileManager.hasLocation(StandardLocation.MODULE_SOURCE_PATH);
             ClassWriter classWriter = ClassWriter.instance(context);
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
    index 9e3a978c3bc..7aa1cc473b5 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java
    @@ -503,7 +503,7 @@ public boolean validate() {
                         }
                     } else {
                         // single-module or legacy mode
    -                    boolean lintPaths = !options.isExplicitlyDisabled(Option.XLINT, LintCategory.PATH);
    +                    boolean lintPaths = !options.isLintDisabled(LintCategory.PATH);
                         if (lintPaths) {
                             Path outDirParent = outDir.getParent();
                             if (outDirParent != null && Files.exists(outDirParent.resolve("module-info.class"))) {
    @@ -576,7 +576,7 @@ public boolean validate() {
                 reportDiag(Errors.SourcepathModulesourcepathConflict);
             }
     
    -        boolean lintOptions = !options.isExplicitlyDisabled(Option.XLINT, LintCategory.OPTIONS);
    +        boolean lintOptions = !options.isLintDisabled(LintCategory.OPTIONS);
             if (lintOptions && source.compareTo(Source.DEFAULT) < 0 && !options.isSet(Option.RELEASE)) {
                 if (fm instanceof BaseFileManager baseFileManager) {
                     if (source.compareTo(Source.JDK8) <= 0) {
    diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java
    index 63f5b0ca75a..32a31028b68 100644
    --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java
    +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java
    @@ -172,55 +172,67 @@ public boolean isUnset(Option option, String value) {
         }
     
         /**
    -     * Check whether the given lint category is explicitly enabled or disabled.
    +     * Determine if a specific {@link LintCategory} is enabled via a custom
    +     * option flag of the form {@code -Xlint}, {@code -Xlint:all}, or {@code -Xlint:key}.
          *
          * 

    - * If the category is neither enabled nor disabled, return the given default value. + * Note: It's possible the category was also disabled; this method does not check that. * - * @param option the plain (non-custom) option * @param lc the {@link LintCategory} in question - * @param defaultValue presumed default value - * @return true if {@code lc} would be included + * @return true if {@code lc} has been enabled */ - public boolean isSet(Option option, LintCategory lc, boolean defaultValue) { - Option customOption = option.getCustom(); - if (lc.optionList.stream().anyMatch(alias -> isSet(customOption, alias))) { - return true; - } - if (lc.optionList.stream().anyMatch(alias -> isSet(customOption, "-" + alias))) { - return false; - } - if (isSet(option) || isSet(customOption, Option.LINT_CUSTOM_ALL)) { - return true; - } - if (isSet(customOption, Option.LINT_CUSTOM_NONE)) { - return false; - } - return defaultValue; + public boolean isLintEnabled(LintCategory lc) { + return isLintExplicitlyEnabled(lc) || + isSet(Option.XLINT_CUSTOM) || + isSet(Option.XLINT_CUSTOM, Option.LINT_CUSTOM_ALL); } /** - * Determine if a specific {@link LintCategory} was explicitly enabled via a custom option flag - * of the form {@code -Flag:all} or {@code -Flag:key}. + * Determine if a specific {@link LintCategory} is disabled via a custom + * option flag of the form {@code -Xlint:none} or {@code -Xlint:-key}. + * + *

    + * Note: It's possible the category was also enabled; this method does not check that. + * + * @param lc the {@link LintCategory} in question + * @return true if {@code lc} has been disabled + */ + public boolean isLintDisabled(LintCategory lc) { + return isLintExplicitlyDisabled(lc) || isSet(Option.XLINT_CUSTOM, Option.LINT_CUSTOM_NONE); + } + + /** + * Determine if a specific {@link LintCategory} is explicitly enabled via a custom + * option flag of the form {@code -Xlint:key}. + * + *

    + * Note: This does not check for option flags of the form {@code -Xlint} or {@code -Xlint:all}. + * + *

    + * Note: It's possible the category was also disabled; this method does not check that. * - * @param option the option * @param lc the {@link LintCategory} in question * @return true if {@code lc} has been explicitly enabled */ - public boolean isExplicitlyEnabled(Option option, LintCategory lc) { - return isSet(option, lc, false); + public boolean isLintExplicitlyEnabled(LintCategory lc) { + return lc.optionList.stream().anyMatch(alias -> isSet(Option.XLINT_CUSTOM, alias)); } /** - * Determine if a specific {@link LintCategory} was explicitly disabled via a custom option flag - * of the form {@code -Flag:none} or {@code -Flag:-key}. + * Determine if a specific {@link LintCategory} is explicitly disabled via a custom + * option flag of the form {@code -Xlint:-key}. + * + *

    + * Note: This does not check for an option flag of the form {@code -Xlint:none}. + * + *

    + * Note: It's possible the category was also enabled; this method does not check that. * - * @param option the option * @param lc the {@link LintCategory} in question * @return true if {@code lc} has been explicitly disabled */ - public boolean isExplicitlyDisabled(Option option, LintCategory lc) { - return !isSet(option, lc, true); + public boolean isLintExplicitlyDisabled(LintCategory lc) { + return lc.optionList.stream().anyMatch(alias -> isSet(Option.XLINT_CUSTOM, "-" + alias)); } public void put(String name, String value) { diff --git a/test/langtools/tools/javac/lint/LintOptions.java b/test/langtools/tools/javac/lint/LintOptions.java new file mode 100644 index 00000000000..10def72a31a --- /dev/null +++ b/test/langtools/tools/javac/lint/LintOptions.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +/* + * @test + * @bug 8359596 + * @summary Verify behavior when both "-Xlint:options" and "-Xlint:-options" are given + * @compile/fail/ref=LintOptions.out -Werror -XDrawDiagnostics -source 21 -target 21 LintOptions.java + * @compile/fail/ref=LintOptions.out -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:options LintOptions.java + * @compile -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:-options LintOptions.java + * @compile -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:options -Xlint:-options LintOptions.java + * @compile -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:none LintOptions.java + * @compile -Werror -XDrawDiagnostics -source 21 -target 21 -Xlint:options -Xlint:none LintOptions.java + */ +class LintOptions { +} diff --git a/test/langtools/tools/javac/lint/LintOptions.out b/test/langtools/tools/javac/lint/LintOptions.out new file mode 100644 index 00000000000..020c626ee5c --- /dev/null +++ b/test/langtools/tools/javac/lint/LintOptions.out @@ -0,0 +1,4 @@ +- compiler.warn.source.no.system.modules.path: 21, (compiler.misc.source.no.system.modules.path.with.target: 21, 21) +- compiler.err.warnings.and.werror +1 error +1 warning From a23de2ec090628b52532ee5d9bd4364a97499f5b Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 27 Jun 2025 19:10:02 +0000 Subject: [PATCH 213/213] 8360478: libjsig related tier3 jtreg tests fail when asan is configured Reviewed-by: dholmes, ihse --- make/data/asan/asan_default_options.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/make/data/asan/asan_default_options.c b/make/data/asan/asan_default_options.c index 9e0887c5f67..70821045176 100644 --- a/make/data/asan/asan_default_options.c +++ b/make/data/asan/asan_default_options.c @@ -67,6 +67,8 @@ ATTRIBUTE_DEFAULT_VISIBILITY ATTRIBUTE_USED const char* CDECL __asan_default_opt #endif "print_suppressions=0," "handle_segv=0," + // A lot of libjsig related tests fail because of the link order check; so better avoid it + "verify_asan_link_order=0," // See https://github.com/google/sanitizers/issues/1322. Hopefully this is resolved // at some point and we can remove this option. "intercept_tls_get_addr=0";