From ade17ecb6cb5125d048401a878b557e5afefc08c Mon Sep 17 00:00:00 2001 From: Phil Race Date: Sun, 29 Sep 2024 17:05:01 +0000 Subject: [PATCH 01/15] 8340560: Open Source several AWT/2D font and rendering tests Reviewed-by: kizune --- test/jdk/sun/awt/font/CacheFlushTest.java | 106 ++++++++++ test/jdk/sun/awt/font/TestArabicHebrew.java | 215 ++++++++++++++++++++ test/jdk/sun/awt/font/TestDevTransform.java | 155 ++++++++++++++ test/jdk/sun/awt/windows/TestPen.java | 102 ++++++++++ 4 files changed, 578 insertions(+) create mode 100644 test/jdk/sun/awt/font/CacheFlushTest.java create mode 100644 test/jdk/sun/awt/font/TestArabicHebrew.java create mode 100644 test/jdk/sun/awt/font/TestDevTransform.java create mode 100644 test/jdk/sun/awt/windows/TestPen.java diff --git a/test/jdk/sun/awt/font/CacheFlushTest.java b/test/jdk/sun/awt/font/CacheFlushTest.java new file mode 100644 index 0000000000000..f3b3293127530 --- /dev/null +++ b/test/jdk/sun/awt/font/CacheFlushTest.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4286726 + * @summary Java2D raster printing: large text may overflow glyph cache. + * Draw a large glyphvector, the 'A' glyph should appear and not get flushed. +*/ + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.Point2D; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +/** + * Draw a very large glyphvector on a surface. + * If the cache was flushed the first glyph is not rendered. + * Note: the implementation no longer uses glyphs for rendering large text, + * but in principle the test is still useful. + */ +public class CacheFlushTest { + + static final int WIDTH = 400, HEIGHT = 600; + static final int FONTSIZE = 250; + static final String TEST = "ABCDEFGHIJKLMNOP"; + static final HashMap HINTS = new HashMap<>(); + + static { + HINTS.put(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + HINTS.put(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + HINTS.put(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_ON); + } + + public static void main(String args[]) { + BufferedImage bi = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB); + + Graphics2D g2d = bi.createGraphics(); + g2d.addRenderingHints(HINTS); + g2d.setColor(Color.white); + g2d.fillRect(0, 0, WIDTH, HEIGHT); + g2d.setColor(Color.black); + + FontRenderContext frc = g2d.getFontRenderContext(); + Font font = new Font(Font.DIALOG, Font.PLAIN, 250); + GlyphVector gv = font.createGlyphVector(frc, TEST); + + /* Set the positions of all but the first glyph to be offset vertically but + * FONTSIZE pixels. So if the first glyph "A" is not flushed we can tell this + * by checking for non-white pixels in the range for the default y offset of 0 + * from the specified y location. + */ + Point2D.Float pt = new Point2D.Float(20f, FONTSIZE); + for (int i = 1; i < gv.getNumGlyphs(); ++i) { + gv.setGlyphPosition(i, pt); + pt.x += 25f; + pt.y = FONTSIZE; + } + g2d.drawGlyphVector(gv, 20, FONTSIZE); + /* Now expect to find at least one black pixel in the rect (0,0) -> (WIDTH, FONTSIZE) */ + boolean found = false; + int blackPixel = Color.black.getRGB(); + for (int y = 0; y < FONTSIZE; y++) { + for (int x = 0; x < WIDTH; x++) { + if (bi.getRGB(x, y) == blackPixel) { + found = true; + break; + } + } + if (found == true) { + break; + } + } + if (!found) { + throw new RuntimeException("NO BLACK PIXELS"); + } + } +} diff --git a/test/jdk/sun/awt/font/TestArabicHebrew.java b/test/jdk/sun/awt/font/TestArabicHebrew.java new file mode 100644 index 0000000000000..61cbe931c32c4 --- /dev/null +++ b/test/jdk/sun/awt/font/TestArabicHebrew.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4198081 + * @key headful + * @summary Arabic characters should appear instead of boxes and be correctly shaped. + * Hebrew characters should appear instead of boxes. + * Test is made headful so there's no excuse for test systems not having the fonts. + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Panel; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.geom.Rectangle2D; + +public class TestArabicHebrew extends Panel { + + static volatile Frame frame; + static volatile Font font = new Font(Font.DIALOG, Font.PLAIN, 36); + + static void createUI() { + frame = new Frame("Test Arabic/Hebrew"); + frame.setLayout(new BorderLayout()); + TestArabicHebrew panel = new TestArabicHebrew(); + frame.add(panel, BorderLayout.CENTER); + frame.pack(); + frame.setVisible(true); + } + + public static void main(String args[]) throws Exception { + EventQueue.invokeAndWait(TestArabicHebrew::createUI); + try { + checkStrings(); + } finally { + if (frame != null && args.length == 0) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } + + static void checkString(String script, String str) { + int index = font.canDisplayUpTo(str); + if (index != -1) { + throw new RuntimeException("Cannot display char " + index + " for " + script); + } + } + + static void checkStrings() { + checkString("Arabic", arabic); + checkString("Hebrew", hebrew); + checkString("Latin-1 Supplement", latin1sup); + } + + // Table of arabic unicode characters - minimal support level + // Includes arabic chars from basic block up to 0652 and + // corresponding shaped characters from the arabic + // extended-B block from fe80 to fefc (does include lam-alef + // ligatures). + // Does not include arabic-indic digits nor "arabic extended" + // range. + + static final String arabic = + "\u060c\u061b\u061f\u0621\u0622\u0623\u0624\u0625\u0626\u0627" + + "\u0628\u0629\u062a\u062b\u062c\u062d\u062e\u062f\u0630\u0631" + + "\u0632\u0633\u0634\u0635\u0636\u0637\u0638\u0639\u063a\u0640" + + "\u0641\u0642\u0643\u0644\u0645\u0646\u0647\u0648\u0649\u064a" + + "\u064b\u064c\u064d\u064e\u064f\u0650\u0651\u0652\ufe80\ufe81" + + "\ufe82\ufe83\ufe84\ufe85\ufe86\ufe87\ufe88\ufe89\ufe8a\ufe8b" + + "\ufe8c\ufe8d\ufe8e\ufe8f\ufe90\ufe91\ufe92\ufe93\ufe94\ufe95" + + "\ufe96\ufe97\ufe98\ufe99\ufe9a\ufe9b\ufe9c\ufe9d\ufe9e\ufe9f" + + "\ufea0\ufea1\ufea2\ufea3\ufea4\ufea5\ufea6\ufea7\ufea8\ufea9" + + "\ufeaa\ufeab\ufeac\ufead\ufeae\ufeaf\ufeb0\ufeb1\ufeb2\ufeb3" + + "\ufeb4\ufeb5\ufeb6\ufeb7\ufeb8\ufeb9\ufeba\ufebb\ufebc\ufebd" + + "\ufebe\ufebf\ufec0\ufec1\ufec2\ufec3\ufec4\ufec5\ufec6\ufec7" + + "\ufec8\ufec9\ufeca\ufecb\ufecc\ufecd\ufece\ufecf\ufed0\ufed1" + + "\ufed2\ufed3\ufed4\ufed5\ufed6\ufed7\ufed8\ufed9\ufeda\ufedb" + + "\ufedc\ufedd\ufede\ufedf\ufee0\ufee1\ufee2\ufee3\ufee4\ufee5" + + "\ufee6\ufee7\ufee8\ufee9\ufeea\ufeeb\ufeec\ufeed\ufeee\ufeef" + + "\ufef0\ufef1\ufef2\ufef3\ufef4\ufef5\ufef6\ufef7\ufef8\ufef9" + + "\ufefa\ufefb\ufefc"; + + // hebrew table includes all characters in hebrew block + + static final String hebrew = + "\u0591\u0592\u0593\u0594\u0595\u0596\u0597\u0598\u0599\u059a" + + "\u059b\u059c\u059d\u059e\u059f\u05a0\u05a1\u05a3\u05a4\u05a5" + + "\u05a6\u05a7\u05a8\u05a9\u05aa\u05ab\u05ac\u05ad\u05ae\u05af" + + "\u05b0\u05b1\u05b2\u05b3\u05b4\u05b5\u05b6\u05b7\u05b8\u05b9" + + "\u05bb\u05bc\u05bd\u05be\u05bf\u05c0\u05c1\u05c2\u05c3\u05c4" + + "\u05d0\u05d1\u05d2\u05d3\u05d4\u05d5\u05d6\u05d7\u05d8\u05d9" + + "\u05da\u05db\u05dc\u05dd\u05de\u05df\u05e0\u05e1\u05e2\u05e3" + + "\u05e4\u05e5\u05e6\u05e7\u05e8\u05e9\u05ea\u05f0\u05f1\u05f2" + + "\u05f3\u05f4"; + + // latin 1 supplement table includes all non-control characters + // in this range. Included because of comment in code that claims + // some problems displaying this range with some SJIS fonts. + + static final String latin1sup = + "\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7" + + "\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af\u00b0\u00b1" + + "\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb" + + "\u00bc\u00bd\u00be\u00bf\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5" + + "\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf" + + "\u00d0\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9" + + "\u00da\u00db\u00dc\u00dd\u00de\u00df\u00e0\u00e1\u00e2\u00e3" + + "\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed" + + "\u00ee\u00ef\u00f0\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7" + + "\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u00fe\u00ff"; + + public TestArabicHebrew() { + setLayout(new GridLayout(3, 1)); + + FontRenderContext frc = new FontRenderContext(null, false, false); + add(new SubGlyphPanel("Arabic", arabic, font, frc)); + add(new SubGlyphPanel("Hebrew", hebrew, font, frc)); + add(new SubGlyphPanel("Latin-1 Supplement", latin1sup, font, frc)); + } + + static class SubGlyphPanel extends Panel { + String title; + Dimension extent; + GlyphVector[] vectors; + + static final int kGlyphsPerLine = 20; + + SubGlyphPanel(String title, String chars, Font font, FontRenderContext frc) { + + this.title = title; + setBackground(Color.white); + + double width = 0; + double height = 0; + + int max = chars.length(); + vectors = new GlyphVector[(max + kGlyphsPerLine - 1) / kGlyphsPerLine]; + for (int i = 0; i < vectors.length; i++) { + int start = i * 20; + int limit = Math.min(max, (i + 1) * kGlyphsPerLine); + String substr = ""; + for (int j = start; j < limit; ++j) { + substr = substr.concat(chars.charAt(j) + " "); + } + GlyphVector gv = font.createGlyphVector(frc, substr); + vectors[i] = gv; + Rectangle2D bounds = gv.getLogicalBounds(); + + width = Math.max(width, bounds.getWidth()); + height += bounds.getHeight(); + } + + extent = new Dimension((int)(width + 1), (int)(height + 1 + 30)); // room for title + + setSize(getPreferredSize()); + } + + public Dimension getPreferredSize() { + return new Dimension(extent); + } + + public Dimension getMinimumSize() { + return getPreferredSize(); + } + + public Dimension getMaximumSize() { + return getPreferredSize(); + } + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + + g.drawString(title, 10, 20); + + float x = 10; + float y = 30; + for (int i = 0; i < vectors.length; ++i) { + GlyphVector gv = vectors[i]; + Rectangle2D bounds = gv.getLogicalBounds(); + g2d.drawGlyphVector(gv, x, (float)(y - bounds.getY())); + y += bounds.getHeight(); + } + } + } +} diff --git a/test/jdk/sun/awt/font/TestDevTransform.java b/test/jdk/sun/awt/font/TestDevTransform.java new file mode 100644 index 0000000000000..035cb0b13d73a --- /dev/null +++ b/test/jdk/sun/awt/font/TestDevTransform.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4269775 + * @summary Check that different text rendering APIs agree + */ + +/** + * Draw into an image rendering the same text string nine different + * ways: as a TextLayout, a simple String, and a GlyphVector, each + * with three different x scale factors. The expectation is that each + * set of three strings would appear the same although offset in y to + * avoid overlap. The bug was that the y positions of the individual characters + * of the TextLayout and GlyphVector were wrong, so the strings appeared + * to be rendered at different angles. + */ + +import java.awt.Color; +import java.awt.Font; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphVector; +import java.awt.font.TextLayout; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.util.HashMap; + +public class TestDevTransform { + + static HashMap hints = new HashMap<>(); + + static { + hints.put(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + hints.put(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + hints.put(RenderingHints.KEY_FRACTIONALMETRICS, + RenderingHints.VALUE_FRACTIONALMETRICS_ON); + } + + static String test = "This is only a test"; + static double angle = Math.PI / 6.0; // Rotate 30 degrees + static final int W = 400, H = 400; + + static void draw(Graphics2D g2d, TextLayout layout, + float x, float y, float scalex) { + AffineTransform saveTransform = g2d.getTransform(); + g2d.translate(x, y); + g2d.rotate(angle); + g2d.scale(scalex, 1f); + layout.draw(g2d, 0f, 0f); + g2d.setTransform(saveTransform); + } + + static void draw(Graphics2D g2d, String string, + float x, float y, float scalex) { + AffineTransform saveTransform = g2d.getTransform(); + g2d.translate(x, y); + g2d.rotate(angle); + g2d.scale(scalex, 1f); + g2d.drawString(string, 0f, 0f); + g2d.setTransform(saveTransform); + } + + static void draw(Graphics2D g2d, GlyphVector gv, + float x, float y, float scalex) { + AffineTransform saveTransform = g2d.getTransform(); + g2d.translate(x, y); + g2d.rotate(angle); + g2d.scale(scalex, 1f); + g2d.drawGlyphVector(gv, 0f, 0f); + g2d.setTransform(saveTransform); + } + + static void init(Graphics2D g2d) { + g2d.setColor(Color.white); + g2d.fillRect(0, 0, W, H); + g2d.setColor(Color.black); + g2d.scale(1.481f, 1.481); // Convert to 108 dpi + g2d.addRenderingHints(hints); + Font font = new Font(Font.DIALOG, Font.PLAIN, 12); + g2d.setFont(font); + } + + static void compare(BufferedImage bi1, BufferedImage bi2) { + for (int x = 0; x < bi1.getWidth(); x++) { + for (int y = 0; y < bi1.getHeight(); y++) { + if (bi1.getRGB(x, y) != bi2.getRGB(x, y)) { + throw new RuntimeException("Different rendering"); + } + } + } + } + + public static void main(String args[]) { + + BufferedImage tl_Image = new BufferedImage(W, H, BufferedImage.TYPE_INT_RGB); + { + Graphics2D tl_g2d = tl_Image.createGraphics(); + init(tl_g2d); + FontRenderContext frc = tl_g2d.getFontRenderContext(); + // Specify font from graphics to be sure it is the same as the other cases. + TextLayout tl = new TextLayout(test, tl_g2d.getFont(), frc); + draw(tl_g2d, tl, 10f, 12f, 3.0f); + draw(tl_g2d, tl, 10f, 24f, 1.0f); + draw(tl_g2d, tl, 10f, 36f, 0.33f); + } + + BufferedImage st_Image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB); + { + Graphics2D st_g2d = st_Image.createGraphics(); + init(st_g2d); + draw(st_g2d, test, 10f, 12f, 3.0f); + draw(st_g2d, test, 10f, 24f, 1.0f); + draw(st_g2d, test, 10f, 36f, .33f); + } + + BufferedImage gv_Image = new BufferedImage(400, 400, BufferedImage.TYPE_INT_RGB); + { + Graphics2D gv_g2d = gv_Image.createGraphics(); + init(gv_g2d); + FontRenderContext frc = gv_g2d.getFontRenderContext(); + GlyphVector gv = gv_g2d.getFont().createGlyphVector(frc, test); + draw(gv_g2d, gv, 10f, 12f, 3.0f); + draw(gv_g2d, gv, 10f, 24f, 1.0f); + draw(gv_g2d, gv, 10f, 36f, .33f); + } + + compare(tl_Image, st_Image); + compare(gv_Image, st_Image); + } +} diff --git a/test/jdk/sun/awt/windows/TestPen.java b/test/jdk/sun/awt/windows/TestPen.java new file mode 100644 index 0000000000000..25b7304bdc862 --- /dev/null +++ b/test/jdk/sun/awt/windows/TestPen.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4277201 + * @summary verifies that invoking a fill on a brand new Graphics object + * does not stroke the shape in addition to filling it + * @key headful + */ + +/* + * This test case tests for a problem with initializing GDI graphics + * contexts (HDCs) where a pen is left installed in the graphics object + * even though the AWT believes that there is no Pen installed. The + * result is that when you try to fill a shape, GDI will both fill and + * stroke it. +*/ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; + +public class TestPen extends Panel { + + static volatile TestPen pen; + static volatile Frame frame; + + public TestPen() { + setForeground(Color.black); + setBackground(Color.white); + } + + public Dimension getPreferredSize() { + return new Dimension(200, 200); + } + + public void paint(Graphics g) { + g.setColor(Color.green); + g.fillOval(50, 50, 100, 100); + } + + static void createUI() { + frame = new Frame(); + pen = new TestPen(); + frame.add(pen); + frame.pack(); + frame.setVisible(true); + } + + public static void main(String argv[]) throws Exception { + try { + EventQueue.invokeAndWait(TestPen::createUI); + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(2000); + Point p = pen.getLocationOnScreen(); + Dimension d = pen.getSize(); + Rectangle r = new Rectangle(p.x + 1, p.y + 1, d.width - 2, d.height - 2); + BufferedImage bi = robot.createScreenCapture(r); + int blackPixel = Color.black.getRGB(); + for (int y = 0; y < bi.getHeight(); y++ ) { + for (int x = 0; x < bi.getWidth(); x++ ) { + if (bi.getRGB(x, y) == blackPixel) { + throw new RuntimeException("Black pixel !"); + } + } + } + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } +} From dd56990962d58e4f482773f67bc43383d7748536 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 30 Sep 2024 02:43:32 +0000 Subject: [PATCH 02/15] 8340639: Open source few more AWT List tests Reviewed-by: prr --- .../java/awt/List/HorizScrollWorkTest.java | 69 +++++++++ .../awt/List/HorizScrollbarEraseTest.java | 139 ++++++++++++++++++ .../java/awt/List/ScrollbarPresenceTest.java | 71 +++++++++ test/jdk/java/awt/List/SetForegroundTest.java | 109 ++++++++++++++ 4 files changed, 388 insertions(+) create mode 100644 test/jdk/java/awt/List/HorizScrollWorkTest.java create mode 100644 test/jdk/java/awt/List/HorizScrollbarEraseTest.java create mode 100644 test/jdk/java/awt/List/ScrollbarPresenceTest.java create mode 100644 test/jdk/java/awt/List/SetForegroundTest.java diff --git a/test/jdk/java/awt/List/HorizScrollWorkTest.java b/test/jdk/java/awt/List/HorizScrollWorkTest.java new file mode 100644 index 0000000000000..6de1de1a4f264 --- /dev/null +++ b/test/jdk/java/awt/List/HorizScrollWorkTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. + * 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 6355467 + * @summary Horizontal scroll bar thumb of a List does not stay at the end + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @requires (os.family == "linux") + * @run main/manual HorizScrollWorkTest +*/ + +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; + +public class HorizScrollWorkTest { + + private static final String INSTRUCTIONS = """ + This is a linux only test. + Drag and drop the horizontal scroll bar thumb at the right end. + If the thumb does not stay at the right end, then the test failed. Otherwise passed."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("HorizScrollWorkTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int)INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(HorizScrollWorkTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static Frame createTestUI() { + Frame frame = new Frame("HorizScrollWorkTest Frame"); + List list = new List(4); + + frame.setLayout (new FlowLayout()); + + list.add("veryyyyyyyyyyyyyyyyyyyyyyyyyy longgggggggggggggggggggggg stringggggggggggggggggggggg"); + + frame.add(list); + frame.pack(); + + return frame; + } +} diff --git a/test/jdk/java/awt/List/HorizScrollbarEraseTest.java b/test/jdk/java/awt/List/HorizScrollbarEraseTest.java new file mode 100644 index 0000000000000..2601a7ed0b2e6 --- /dev/null +++ b/test/jdk/java/awt/List/HorizScrollbarEraseTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4895367 + * @summary List scrolling w/ down arrow keys obscures horizontal scrollbar + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @requires (os.family == "linux") + * @run main/manual HorizScrollbarEraseTest + */ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.List; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class HorizScrollbarEraseTest { + + private static final String INSTRUCTIONS = """ + This is a Unix-only test. + Do the four mini-tests below. + If the horizontal scrollbar is ever erased by a rectangle + of the background color, the test FAILS. + If the horizontal scrollbars remain painted, test passes."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("HorizScrollbarEraseTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(HorizScrollbarEraseTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static Frame createTestUI() { + Frame frame = new Frame("HorizScrollbarEraseTest"); + Panel borderPanel = new Panel(); + borderPanel.setLayout(new BorderLayout()); + Button focusedButton = new Button("Focus starts here"); + borderPanel.add(focusedButton, BorderLayout.NORTH); + + Panel gridPanel = new Panel(); + gridPanel.setLayout(new GridLayout(0, 4)); + borderPanel.add(gridPanel, BorderLayout.CENTER); + + InstructionList il1 = new InstructionList("Tab to Item 2, then \n" + + "press the down" + + "arrow key to scroll down"); + il1.list.select(2); + il1.list.makeVisible(0); + gridPanel.add(il1); + + InstructionList il2 = new InstructionList("Tab to the next List,\n" + + "then press the down\n" + + "arrow key to select\n" + + "the last item."); + il2.list.select(3); + il2.list.makeVisible(0); + gridPanel.add(il2); + + InstructionList il3 = new InstructionList("Click the button to\n" + + "programmatically\n" + + "select item 3 (not showing)"); + Button selectBtn = new Button("Click Me"); + final List selectList = il3.list; + selectBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + selectList.select(3); + } + }); + il3.add(selectBtn, BorderLayout.CENTER); + gridPanel.add(il3); + + InstructionList il4 = new InstructionList("Click the button to\nprogrammatically\ndeselect item 3\n(not showing)"); + Button deselectBtn = new Button("Click Me"); + final List deselectList = il4.list; + deselectBtn.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + deselectList.deselect(3); + } + }); + il4.add(deselectBtn, BorderLayout.CENTER); + il4.list.select(3); + il4.list.makeVisible(0); + gridPanel.add(il4); + + frame.add(borderPanel); + frame.pack(); + return frame; + + } +} + +class InstructionList extends Panel { + TextArea ta; + public List list; + + public InstructionList(String instructions) { + super(); + setLayout(new BorderLayout()); + ta = new TextArea(instructions, 6, 25, TextArea.SCROLLBARS_NONE); + ta.setFocusable(false); + list = new List(); + for (int i = 0; i < 5; i++) { + list.add("Item " + i + ", a long, long, long, long item"); + } + add(ta, BorderLayout.NORTH); + add(list, BorderLayout.SOUTH); + } +} diff --git a/test/jdk/java/awt/List/ScrollbarPresenceTest.java b/test/jdk/java/awt/List/ScrollbarPresenceTest.java new file mode 100644 index 0000000000000..d82cbb80060ca --- /dev/null +++ b/test/jdk/java/awt/List/ScrollbarPresenceTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. + * 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 6336384 + * @summary ScrollBar does not show up correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollbarPresenceTest +*/ + +import java.awt.Font; +import java.awt.Frame; +import java.awt.List; + +public class ScrollbarPresenceTest { + + private static final String INSTRUCTIONS = """ + You will see a list, + If a vertical scrollbar appears on the list and the list is big enough + to show all items then the test failed else the test passed."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("ScrollbarPresenceTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(ScrollbarPresenceTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static Frame createTestUI() { + Frame frame = new Frame("ScrollbarPresenceTest Frame"); + List list = new List(); + + for (int i = 0; i < 6; i++) { + list.addItem("Row " + i); + } + + list.setFont(new Font("MonoSpaced", Font.PLAIN, 12)); + list.setBounds(30, 30, 128, 104); + frame.add(list); + + frame.pack(); + return frame; + } + +} diff --git a/test/jdk/java/awt/List/SetForegroundTest.java b/test/jdk/java/awt/List/SetForegroundTest.java new file mode 100644 index 0000000000000..7b22e5385088b --- /dev/null +++ b/test/jdk/java/awt/List/SetForegroundTest.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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 6246467 + * @summary Tests that list works correctly if user specified foreground colors on XToolkit/Motif + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SetForegroundTest + */ + +import java.awt.Button; +import java.awt.Component; +import java.awt.Checkbox; +import java.awt.Choice; +import java.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.List; +import java.awt.Panel; +import java.awt.TextArea; +import java.awt.TextField; +import java.awt.ScrollPane; + +public class SetForegroundTest { + + private static final String INSTRUCTIONS = """ + To make sure, that for each component + (Button, Checkbox, Label, List, TextArea, TextField, Choice) + in the frame, + the title exist and the color of the title is red. + If not, the test failed."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("SetForegroundTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(SetForegroundTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static Frame createTestUI() { + Frame frame = new Frame(); + ScrollPane sp = new ScrollPane() { + public Dimension getPreferredSize() { + return new Dimension(180, 180); + } + }; + Panel p = new Panel(); + Component childs[] = new Component[] {new Button("button"), + new Checkbox("checkbox"), + new Label("label"), + new List(3, false), + new TextArea("text area"), + new TextField("text field"), + new Choice()}; + + p.setLayout (new FlowLayout ()); + + sp.add(p); + + sp.validate(); + + frame.add(sp); + for (int i = 0; i < childs.length; i++){ + childs[i].setForeground(Color.red); + } + + for (int i = 0; i < childs.length; i++) { + p.add(childs[i]); + if (childs[i] instanceof List) { + ((List)childs[i]).add("list1"); + ((List)childs[i]).add("list2"); + } else if (childs[i] instanceof Choice) { + ((Choice)childs[i]).add("choice1"); + ((Choice)childs[i]).add("choice2"); + } + } + frame.pack(); + return frame; + } +} From ae4d2f15901bf02efceaac26ee4aa3ae666bf467 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 30 Sep 2024 02:43:49 +0000 Subject: [PATCH 03/15] 8340621: Open source several AWT List tests Reviewed-by: prr --- .../java/awt/List/DisabledListIsGreyTest.java | 75 ++++++++++ .../java/awt/List/ListFrameResizeTest.java | 104 ++++++++++++++ .../awt/List/MultiSelectionListCrashTest.java | 89 ++++++++++++ .../java/awt/List/ScrollbarPositionTest.java | 104 ++++++++++++++ .../awt/List/SelectedItemVisibilityTest.java | 128 ++++++++++++++++++ 5 files changed, 500 insertions(+) create mode 100644 test/jdk/java/awt/List/DisabledListIsGreyTest.java create mode 100644 test/jdk/java/awt/List/ListFrameResizeTest.java create mode 100644 test/jdk/java/awt/List/MultiSelectionListCrashTest.java create mode 100644 test/jdk/java/awt/List/ScrollbarPositionTest.java create mode 100644 test/jdk/java/awt/List/SelectedItemVisibilityTest.java diff --git a/test/jdk/java/awt/List/DisabledListIsGreyTest.java b/test/jdk/java/awt/List/DisabledListIsGreyTest.java new file mode 100644 index 0000000000000..ec1a257066606 --- /dev/null +++ b/test/jdk/java/awt/List/DisabledListIsGreyTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. + * 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 6354810 + * @summary Items in the list are not grayed out when disabled, XToolkit + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual DisabledListIsGreyTest +*/ + +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; + +public class DisabledListIsGreyTest { + + private static final String INSTRUCTIONS = """ + 1) After the test started you will see two lists. + 2) One of them is enabled, and the second is disabled. + 3) Check that the items of the disabled list are grayed. + 4) If so, the test passed. Otherwise, failed."""; + + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("DisabledListIsGreyTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(DisabledListIsGreyTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static Frame createTestUI() { + Frame frame = new Frame("DisabledListIsGreyTest Frame"); + frame.setLayout(new FlowLayout()); + + List list1 = new List(3); + List list2 = new List(3); + for (int i = 0; i < 5; i++) { + list1.addItem("Item " + i); + list2.addItem("Item " + i); + } + frame.add(list1); + + list2.setEnabled(false); + frame.add(list2); + frame.pack(); + return frame; + } + +} diff --git a/test/jdk/java/awt/List/ListFrameResizeTest.java b/test/jdk/java/awt/List/ListFrameResizeTest.java new file mode 100644 index 0000000000000..4655e817da581 --- /dev/null +++ b/test/jdk/java/awt/List/ListFrameResizeTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. + * 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 4085379 + * @summary List component not properly "resized" with GridBagLayout + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ListFrameResizeTest + */ + +import java.awt.Color; +import java.awt.Frame; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.List; + +public class ListFrameResizeTest { + + private static final String INSTRUCTIONS = """ + This test is for windows only. + + 1. A Frame will appear with a List + (the List occupies the whole Frame) + 2. Minimize the Frame, the Frame is now in the Task Bar (ie.,iconified) + 3. Right click (right mouse button) the icon in the task bar + and click on the 'maximize' menuitem to maximize the Frame + 4. If you notice the List has not been resized + (ie.,if it partly occupies the Frame), then press FAIL else press PASS"."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("ListFrameResizeTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(ListFrameResizeTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static Frame createTestUI() { + wintest client = new wintest("ListFrameResizeTest Frame"); + client.resize(500, 300); + client.setBackground(Color.blue); + return client; + } + +} + +class wintest extends Frame { + private List msg; + + public wintest(String title) { + super(title); + msg = new List(); + for (int i = 0; i < 100; i++) { + msg.add("" + i); + } + + GridBagLayout gridbag = new GridBagLayout(); + GridBagConstraints constraints = new GridBagConstraints(); + + setLayout(gridbag); + + constraints.fill = GridBagConstraints.BOTH; + + constraints.anchor = GridBagConstraints.CENTER; + constraints.insets = new Insets(10, 10, 10, 10); + constraints.ipadx = 0; + constraints.ipady = 0; + constraints.weightx = 1; + constraints.weighty = 1; + constraints.gridx = 0; + constraints.gridy = 0; + constraints.gridwidth = GridBagConstraints.REMAINDER; + constraints.gridheight = GridBagConstraints.REMAINDER; + gridbag.setConstraints(msg, constraints); + add(msg); + } +} diff --git a/test/jdk/java/awt/List/MultiSelectionListCrashTest.java b/test/jdk/java/awt/List/MultiSelectionListCrashTest.java new file mode 100644 index 0000000000000..b408a12ebbac7 --- /dev/null +++ b/test/jdk/java/awt/List/MultiSelectionListCrashTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4201967 + * @summary tests that a multiselection list doesn't causes crash when FileDialog is invoked + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual MultiSelectionListCrashTest + */ + +import java.awt.Button; +import java.awt.FileDialog; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class MultiSelectionListCrashTest { + + private static final String INSTRUCTIONS = """ + Press "Invoke dialog" button to invoke a FileDialog. + When it appears close it by pressing cancel button. + If all remaining frames are enabled and + page fault didn't occur the test passed. Otherwise the test failed. + + Try to invoke a FileDialog several times to verify that the bug doesn't exist."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("MultiSelectionListCrashTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(MultiSelectionListCrashTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static Frame createTestUI() { + + Frame frame = new Frame("MultiSelectionListCrashTest frame"); + Button button = new Button("Invoke dialog"); + button.addActionListener(new FileDialogInvoker(frame)); + List list = new List(4, true); + list.add("Item1"); + list.add("Item2"); + frame.setLayout(new FlowLayout()); + frame.add(button); + frame.add(list); + frame.setSize(200, 200); + return frame; + } +} + +class FileDialogInvoker implements ActionListener { + FileDialog fileDialog; + + public FileDialogInvoker(Frame frame) { + fileDialog = new FileDialog(frame); + } + + public void actionPerformed(ActionEvent e) { + fileDialog.setVisible(true); + } + +} diff --git a/test/jdk/java/awt/List/ScrollbarPositionTest.java b/test/jdk/java/awt/List/ScrollbarPositionTest.java new file mode 100644 index 0000000000000..25167fa56278c --- /dev/null +++ b/test/jdk/java/awt/List/ScrollbarPositionTest.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4024943 + * @summary Test for position of List scrollbar when it is added + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ScrollbarPositionTest + */ + +import java.awt.Button; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.List; +import java.awt.Panel; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class ScrollbarPositionTest { + static int item = 0; + static List list; + static Button addButton, delButton; + + private static final String INSTRUCTIONS = """ + Click on the "Add List Item" button many times + until the vertical scrollbar appears. + Verify that the displayed vertical scrollbar does not take the space + that was occupied by buttons before the scrollbar is shown."""; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("ScrollbarPositionTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(ScrollbarPositionTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static Frame createTestUI() { + Panel pan; + + Frame frame = new Frame("ScrollbarPositionTest Frame"); + frame.setLayout(new GridLayout(1, 2)); + list = new List(); + frame.add(list); + frame.add(pan = new Panel()); + pan.setLayout(new GridLayout(4, 1)); + + MyListener listener = new MyListener(); + addButton = new Button("Add List Item"); + addButton.addActionListener(listener); + pan.add(addButton); + + delButton = new Button("Delete List Item"); + delButton.addActionListener(listener); + pan.add(delButton); + + frame.pack(); + return frame; + } + + static class MyListener implements ActionListener { + public void actionPerformed(ActionEvent evt) { + if (evt.getSource() == addButton) { + String s = "item"; + for (int i = 0; i <= item; i++) { + s = s +" "+Integer.toString(i); + } + item++; + list.addItem(s); + } else if (evt.getSource() == delButton) { + int i; + if ((i = list.countItems()) > 0) { + list.delItem(i - 1); + --item; + } + } + } + } +} diff --git a/test/jdk/java/awt/List/SelectedItemVisibilityTest.java b/test/jdk/java/awt/List/SelectedItemVisibilityTest.java new file mode 100644 index 0000000000000..53364e937713c --- /dev/null +++ b/test/jdk/java/awt/List/SelectedItemVisibilityTest.java @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4676536 + * @summary REGRESSION: makeVisible() method of List Component does not perform + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual SelectedItemVisibilityTest + */ + +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.List; + +public class SelectedItemVisibilityTest { + + static List list1, list2; + static int visibleItem = 4; + static int selectedItems[] = {6, 7, 8}; + static String selectedItemsStr = ""; + + static { + for (int i = 0 ; i < selectedItems.length ; i++) { + selectedItemsStr += ""+selectedItems[i]+" "; + } + } + + private static final String INSTRUCTIONS = + "You should see two lists.\n" + + "\n" + + "list1: \n" + + "\t1. the first visible item should be " + visibleItem + + "\n\t2. the selected item should be " + selectedItems[0] + + "\n" + + "list2:\n" + + "\t1. the first visible item should be " + visibleItem + + "\n\t2. the selected items should be " + selectedItemsStr + + "\n" + + "\nIf it is so the test passed else failed."; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("SelectedItemVisibilityTest Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(SelectedItemVisibilityTest::createTestUI) + .logArea() + .build() + .awaitAndCheck(); + } + + private static Frame createTestUI() { + + Frame frame = new Frame("SelectedItemVisibilityTest Frame"); + frame.setLayout(new FlowLayout()); + + // list1 + list1 = new List(4); + for (int i = 0; i < 20; i++) { + list1.add(""+i); + } + list1.makeVisible(visibleItem); + list1.select(selectedItems[0]); + frame.add(new Label("list1:")); + frame.add(list1); + + // list2 + list2 = new List(4); + list2.setMultipleMode(true); + for (int i = 0; i < 20; i++) { + list2.add(""+i); + } + list2.makeVisible(visibleItem); + for (int i = 0 ; i < selectedItems.length ; i++) { + list2.select(selectedItems[i]); + } + frame.add(new Label("list2:")); + frame.add(list2); + frame.setSize(200, 200); + + // common output + String s; + int sel[]; + + PassFailJFrame.log("list1: "); + PassFailJFrame.log("\tgetVisibleIndex="+list1.getVisibleIndex()); + sel = list1.getSelectedIndexes(); + s = "\tgetSelectedIndexes="; + for (int i = 0 ; i < sel.length ; i++) { + s += "" + sel[i] + " "; + } + PassFailJFrame.log(s); + + PassFailJFrame.log("list2: "); + PassFailJFrame.log("\tgetVisibleIndex="+list2.getVisibleIndex()); + sel = list2.getSelectedIndexes(); + s = "\tgetSelectedIndexes="; + for (int i = 0 ; i < sel.length ; i++) { + s += "" + sel[i] + " "; + } + PassFailJFrame.log(s); + return frame; + } +} From 6514aef8403fa5fc09e5c064a783ff0f1fccd0cf Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Mon, 30 Sep 2024 06:20:08 +0000 Subject: [PATCH 04/15] 8340419: ZGC: Create an UseLargePages adaptation of TestAllocateHeapAt.java Reviewed-by: stefank, sjohanss, jsikstro --- .../gc/z/TestAllocateHeapAtWithHugeTLBFS.java | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 test/hotspot/jtreg/gc/z/TestAllocateHeapAtWithHugeTLBFS.java diff --git a/test/hotspot/jtreg/gc/z/TestAllocateHeapAtWithHugeTLBFS.java b/test/hotspot/jtreg/gc/z/TestAllocateHeapAtWithHugeTLBFS.java new file mode 100644 index 0000000000000..ac647bbd013fd --- /dev/null +++ b/test/hotspot/jtreg/gc/z/TestAllocateHeapAtWithHugeTLBFS.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package gc.z; + +/* + * @test TestAllocateHeapAtWithHugeTLBFS + * @requires vm.gc.ZGenerational & os.family == "linux" + * @summary Test ZGC with -XX:AllocateHeapAt and -XX:+UseLargePages + * @library /test/lib + * @run driver gc.z.TestAllocateHeapAtWithHugeTLBFS true + * @run driver gc.z.TestAllocateHeapAtWithHugeTLBFS false + */ + +import jdk.test.lib.process.ProcessTools; +import jtreg.SkippedException; + +import java.io.File; +import java.io.FileNotFoundException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.Scanner; + +public class TestAllocateHeapAtWithHugeTLBFS { + static String find_hugetlbfs_mountpoint() { + Pattern pat = Pattern.compile("\\d+ \\d+ \\d+:\\d+ \\S+ (\\S+) [^-]*- hugetlbfs (.+)"); + try (Scanner scanner = new Scanner(new File("/proc/self/mountinfo"))) { + while (scanner.hasNextLine()) { + final Matcher mat = pat.matcher(scanner.nextLine()); + if (mat.matches() && mat.group(2).contains("pagesize=2M")) { + final Path path = Paths.get(mat.group(1)); + if (Files.isReadable(path) && + Files.isWritable(path) && + Files.isExecutable(path)) { + // Found a usable mount point. + return path.toString(); + } + } + } + } catch (FileNotFoundException e) { + System.out.println("Could not open /proc/self/mountinfo"); + } + return null; + } + public static void main(String[] args) throws Exception { + final boolean exists = Boolean.parseBoolean(args[0]); + final String directory = exists ? find_hugetlbfs_mountpoint() + : "non-existing-directory"; + if (directory == null) { + throw new SkippedException("No valid hugetlbfs mount point found"); + } + final String heapBackingFile = "Heap Backing File: " + directory; + final String failedToCreateFile = "Failed to create file " + directory; + + ProcessTools.executeTestJava( + "-XX:+UseZGC", + "-XX:+ZGenerational", + "-Xlog:gc*", + "-Xms32M", + "-Xmx32M", + "-XX:+UseLargePages", + "-XX:AllocateHeapAt=" + directory, + "-version") + .shouldContain(exists ? heapBackingFile : failedToCreateFile) + .shouldNotContain(exists ? failedToCreateFile : heapBackingFile) + .shouldHaveExitValue(exists ? 0 : 1); + } +} From 822a773873c42ea27a6be90da92b2b2c9fb8caee Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Mon, 30 Sep 2024 06:38:42 +0000 Subject: [PATCH 05/15] 8340605: Open source several AWT PopupMenu tests Reviewed-by: tr --- .../java/awt/PopupMenu/PeripheryOfScreen.java | 82 ++++++++++++++ .../PopupMenu/PopupLeadingSeparatorTest.java | 81 ++++++++++++++ .../java/awt/PopupMenu/PopupMenuShowTest.java | 77 +++++++++++++ .../awt/PopupMenu/PopupMenuWithMenuBar.java | 103 ++++++++++++++++++ .../jdk/java/awt/PopupMenu/PopupOnButton.java | 88 +++++++++++++++ 5 files changed, 431 insertions(+) create mode 100644 test/jdk/java/awt/PopupMenu/PeripheryOfScreen.java create mode 100644 test/jdk/java/awt/PopupMenu/PopupLeadingSeparatorTest.java create mode 100644 test/jdk/java/awt/PopupMenu/PopupMenuShowTest.java create mode 100644 test/jdk/java/awt/PopupMenu/PopupMenuWithMenuBar.java create mode 100644 test/jdk/java/awt/PopupMenu/PopupOnButton.java diff --git a/test/jdk/java/awt/PopupMenu/PeripheryOfScreen.java b/test/jdk/java/awt/PopupMenu/PeripheryOfScreen.java new file mode 100644 index 0000000000000..b169a7d9692a7 --- /dev/null +++ b/test/jdk/java/awt/PopupMenu/PeripheryOfScreen.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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.Button; +import java.awt.Frame; +import java.awt.MenuItem; +import java.awt.PopupMenu; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/* + * @test + * @bug 6267162 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Popup Menu gets hidden below the screen when opened near the periphery + * of the screen, XToolkit Test if popup menu window is adjusted on screen + * when trying to show outside + * @run main/manual PeripheryOfScreen + */ + +public class PeripheryOfScreen { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + Click on the button to show popup menu in the center of + frame. Move frame beyond the edge of screen and click on + button to show the popup menu and see if popup menu is + adjusted to the edge. + + Press Pass if popup menu behaves as per instruction, otherwise + press Fail. + """; + + PassFailJFrame.builder() + .title("PeripheryOfScreen Instruction") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(PeripheryOfScreen::createUI) + .build() + .awaitAndCheck(); + } + + private static Frame createUI () { + Frame f = new Frame("PeripheryOfScreen Test frame"); + Button b = new Button("Click to show popup menu"); + PopupMenu pm = new PopupMenu("Test menu"); + MenuItem i = new MenuItem("Click me"); + pm.add(i); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + pm.show(f, 100, 100); + } + }); + f.add(b); + f.add(pm); + f.setSize(300, 200); + f.toFront(); + return f; + } +} diff --git a/test/jdk/java/awt/PopupMenu/PopupLeadingSeparatorTest.java b/test/jdk/java/awt/PopupMenu/PopupLeadingSeparatorTest.java new file mode 100644 index 0000000000000..c9274e9b807f0 --- /dev/null +++ b/test/jdk/java/awt/PopupMenu/PopupLeadingSeparatorTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.Component; +import java.awt.Frame; +import java.awt.Font; +import java.awt.MenuItem; +import java.awt.PopupMenu; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/* + * @test + * @bug 4169155 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Popup menus get a leading separator on Motif system + * @run main/manual PopupLeadingSeparatorTest + */ + +public class PopupLeadingSeparatorTest { + public static void main(String[] args) throws Exception { + PopupLeadingSeparatorTest obj = new PopupLeadingSeparatorTest(); + String INSTRUCTIONS = """ + Press mouse button on the frame. Popup menu without leading + separator should appear. + If a PopupMenu behaves same, press Pass, else press Fail. + """; + + PassFailJFrame.builder() + .title("PopupLeadingSeparatorTest Instruction") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(obj::createUI) + .build() + .awaitAndCheck(); + } + + private Frame createUI() { + Frame f = new Frame("PopupLeadingSeparatorTest Test"); + PopupMenu popupMenu = new PopupMenu("Popup Menu Title"); + popupMenu.add(new MenuItem("Item1")); + PopupMenu cascadeMenu = new PopupMenu("Multifont menu"); + cascadeMenu.add(new MenuItem("Item1")); + MenuItem item2 = new MenuItem("Item2"); + item2.setFont(new Font("Serif", Font.BOLD, 36)); + cascadeMenu.add(item2); + + popupMenu.add(cascadeMenu); + f.add(popupMenu); + f.setSize(300, 150); + f.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent evt) { + popupMenu.show((Component) evt.getSource(), evt.getX(), evt.getY()); + } + }); + return f; + } +} diff --git a/test/jdk/java/awt/PopupMenu/PopupMenuShowTest.java b/test/jdk/java/awt/PopupMenu/PopupMenuShowTest.java new file mode 100644 index 0000000000000..b36fdc5d19c22 --- /dev/null +++ b/test/jdk/java/awt/PopupMenu/PopupMenuShowTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.FlowLayout; +import java.awt.Frame; +import java.awt.Label; +import java.awt.MenuItem; +import java.awt.PopupMenu; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/* + * @test + * @bug 4168006 4196790 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Popup menu test fails on x86/Solaris 2.6 combination. + * @run main/manual PopupMenuShowTest + */ + +public class PopupMenuShowTest { + public static void main(String[] args) throws Exception { + PopupMenuShowTest obj = new PopupMenuShowTest(); + String INSTRUCTIONS = """ + Press the right mouse button in the PopupTest window. + If a PopupMenu appears, press Pass, else press Fail. + """; + + PassFailJFrame.builder() + .title("PopupMenuShowTest Instruction") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(obj::createUI) + .build() + .awaitAndCheck(); + } + + private Frame createUI() { + Frame f = new Frame("PopupMenuShowTest Test"); + f.setLayout(new FlowLayout()); + f.add(new Label("Press right mouse button inside this frame.")); + f.add(new Label("A pop-up menu should appear.")); + PopupMenu popupMenu = new PopupMenu("Popup Menu Title"); + MenuItem mi = new MenuItem("Menu Item"); + popupMenu.add(mi); + f.add(popupMenu); + f.setSize(400, 350); + f.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + popupMenu.show(e.getComponent(), e.getX(), e.getY()); + } + }); + return f; + } +} diff --git a/test/jdk/java/awt/PopupMenu/PopupMenuWithMenuBar.java b/test/jdk/java/awt/PopupMenu/PopupMenuWithMenuBar.java new file mode 100644 index 0000000000000..1a927e29f84bc --- /dev/null +++ b/test/jdk/java/awt/PopupMenu/PopupMenuWithMenuBar.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import java.awt.PopupMenu; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/* + * @test + * @bug 4038140 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Test for functionality of PopupMenuWithMenuBar + * @run main/manual PopupMenuWithMenuBar + */ + +public class PopupMenuWithMenuBar { + public static void main(String[] args) throws Exception { + PopupMenuWithMenuBar obj = new PopupMenuWithMenuBar(); + String INSTRUCTIONS = """ + There was a bug that prevented the popup menu from appearing properly + (if even at all) for a frame window when there is also a menu bar. + + Right click inside the frame window to display the popup window. If + the popup menu appears normally, then the test is successful and the + bug has been fixed."""; + + PassFailJFrame.builder() + .title("PopupMenuWithMenuBar Instruction") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(obj::createUI) + .build() + .awaitAndCheck(); + } + + private Frame createUI() { + Frame f = new Frame("PopupMenuWithMenuBar Test"); + f.setBounds(10, 10, 300, 250); + MenuBar menuBar = new MenuBar(); + Menu fileMenu = createFileMenu(); + menuBar.add(fileMenu); + f.setMenuBar(menuBar); + PopupMenu popupMenu = createPopupMenu(); + f.add(popupMenu); + f.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + popupMenu.show(f, e.getX(), e.getY()); + } + }); + return f; + } + + private Menu createFileMenu() { + String[] menu1Labels = new String[] + {"Save As", "Save As", "Quit"}; + MenuItem menuItem; + Menu returnMenu = new Menu("File"); + for (int menu1Index = 0; menu1Index < menu1Labels.length; menu1Index++) { + menuItem = new MenuItem(menu1Labels[menu1Index]); + returnMenu.add(menuItem); + } + return returnMenu; + } + + private PopupMenu createPopupMenu() { + String[] popupLabels = new String[] + {"Popup 1", "Popup 2", "Quit"}; + MenuItem menuItem; + PopupMenu returnMenu = new PopupMenu("Popups"); + for (int popupIndex = 0; popupIndex < popupLabels.length; popupIndex++) { + menuItem = new MenuItem(popupLabels[popupIndex]); + returnMenu.add(menuItem); + } + return returnMenu; + } +} diff --git a/test/jdk/java/awt/PopupMenu/PopupOnButton.java b/test/jdk/java/awt/PopupMenu/PopupOnButton.java new file mode 100644 index 0000000000000..581714bf76a85 --- /dev/null +++ b/test/jdk/java/awt/PopupMenu/PopupOnButton.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.Button; +import java.awt.Component; +import java.awt.Frame; +import java.awt.MenuItem; +import java.awt.PopupMenu; + +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +/* + * @test + * @bug 4181790 + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Tests a popup menu on a button. + * @run main/manual PopupOnButton + */ + +public class PopupOnButton { + public static void main(String[] args) throws Exception { + PopupOnButton obj = new PopupOnButton(); + String INSTRUCTIONS = """ + Right-click on the button. + Popup Menu should appear and behave fine. + If a PopupMenu appears, press Pass, else press Fail. + """; + + PassFailJFrame.builder() + .title("PopupOnButton Instruction") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(obj::createUI) + .build() + .awaitAndCheck(); + } + + private Frame createUI() { + Frame f = new Frame("PopupOnButton Test"); + Button b = new Button("button with popup menu"); + PopupMenu m = new PopupMenu("popup"); + m.add(new MenuItem("item1")); + m.add(new MenuItem("item2")); + m.add(new MenuItem("item3")); + b.add(m); + b.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + if (e.isPopupTrigger()) { + m.show((Component) e.getSource(), e.getX(), e.getY()); + } + } + + @Override + public void mouseReleased(MouseEvent e) { + if (e.isPopupTrigger()) { + m.show((Component) e.getSource(), e.getX(), e.getY()); + } + } + }); + + f.add(b); + f.setSize(200, 150); + return f; + } + } From 988a531b097ccbd699d233059d73f41cae24dc5b Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 30 Sep 2024 07:02:55 +0000 Subject: [PATCH 06/15] 8340181: Shenandoah: Cleanup ShenandoahRuntime stubs Reviewed-by: adinn, phh, wkemper --- .../shenandoahBarrierSetAssembler_aarch64.cpp | 10 ++--- .../shenandoahBarrierSetAssembler_ppc.cpp | 8 ++-- .../shenandoahBarrierSetAssembler_riscv.cpp | 10 ++--- .../shenandoahBarrierSetAssembler_x86.cpp | 10 ++--- .../shenandoah/c2/shenandoahBarrierSetC2.cpp | 29 ++++++------- .../shenandoah/c2/shenandoahBarrierSetC2.hpp | 6 +-- .../gc/shenandoah/c2/shenandoahSupport.cpp | 2 +- .../share/gc/shenandoah/shenandoahRuntime.cpp | 41 ++++++++----------- .../share/gc/shenandoah/shenandoahRuntime.hpp | 8 ++-- 9 files changed, 60 insertions(+), 64 deletions(-) diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index 06f4382015603..84d06dbcc7bfd 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp @@ -67,9 +67,9 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec __ push(saved_regs, sp); if (UseCompressedOops) { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop_entry), src, dst, count); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop), src, dst, count); } else { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop_entry), src, dst, count); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop), src, dst, count); } __ pop(saved_regs, sp); __ bind(done); @@ -164,9 +164,9 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, if (expand_call) { assert(pre_val != c_rarg1, "smashed arg"); - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, thread); } else { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, thread); } __ pop(saved, sp); @@ -698,7 +698,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss __ bind(runtime); __ push_call_clobbered_registers(); __ load_parameter(0, pre_val); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, thread); __ pop_call_clobbered_registers(); __ bind(done); diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp index 3cb5c5a628f39..5315080721249 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp @@ -144,9 +144,9 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler *masm, Dec // Invoke runtime. address jrt_address = nullptr; if (UseCompressedOops) { - jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop_entry); + jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop); } else { - jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop_entry); + jrt_address = CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop); } assert(jrt_address != nullptr, "jrt routine cannot be found"); @@ -302,7 +302,7 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_impl(MacroAssembler *masm } // Invoke runtime. - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, R16_thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, R16_thread); // Restore to-be-preserved registers. if (!preserve_gp_registers && preloaded_mode && pre_val->is_volatile()) { @@ -906,7 +906,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss __ push_frame_reg_args(nbytes_save, R11_tmp1); // Invoke runtime. - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), R0_pre_val, R16_thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), R0_pre_val, R16_thread); // Restore to-be-preserved registers. __ pop_frame(); diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp index 9a79a92327723..cc73d14a756f2 100644 --- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp @@ -70,10 +70,10 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec __ push_reg(saved_regs, sp); if (UseCompressedOops) { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop_entry), + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop), src, dst, count); } else { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop_entry), src, dst, count); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop), src, dst, count); } __ pop_reg(saved_regs, sp); __ bind(done); @@ -165,9 +165,9 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, // expand_call should be passed true. if (expand_call) { assert(pre_val != c_rarg1, "smashed arg"); - __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread); + __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, thread); } else { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, thread); } __ pop_reg(saved, sp); @@ -645,7 +645,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss __ bind(runtime); __ push_call_clobbered_registers(); __ load_parameter(0, pre_val); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), pre_val, thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), pre_val, thread); __ pop_call_clobbered_registers(); __ bind(done); diff --git a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp index 47078dff90738..a7682fe0c3879 100644 --- a/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shenandoah/shenandoahBarrierSetAssembler_x86.cpp @@ -163,12 +163,12 @@ void ShenandoahBarrierSetAssembler::arraycopy_prologue(MacroAssembler* masm, Dec assert(dst == rsi, "expected"); assert(count == rdx, "expected"); if (UseCompressedOops) { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop_entry), + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_narrow_oop), src, dst, count); } else #endif { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop_entry), + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::arraycopy_barrier_oop), src, dst, count); } @@ -296,9 +296,9 @@ void ShenandoahBarrierSetAssembler::satb_write_barrier_pre(MacroAssembler* masm, __ push(thread); __ push(pre_val); #endif - __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), 2); + __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), 2); } else { - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), LP64_ONLY(c_rarg0) NOT_LP64(pre_val), thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), LP64_ONLY(c_rarg0) NOT_LP64(pre_val), thread); } NOT_LP64( __ pop(thread); ) @@ -925,7 +925,7 @@ void ShenandoahBarrierSetAssembler::generate_c1_pre_barrier_runtime_stub(StubAss // load the pre-value __ load_parameter(0, rcx); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), rcx, thread); + __ call_VM_leaf(CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), rcx, thread); __ restore_live_registers(true); diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index 71174d11a6214..10b80b6802942 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -249,8 +249,9 @@ void ShenandoahBarrierSetC2::satb_write_barrier_pre(GraphKit* kit, } __ else_(); { // logging buffer is full, call the runtime - const TypeFunc *tf = ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type(); - __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry), "shenandoah_wb_pre", pre_val, tls); + const TypeFunc *tf = ShenandoahBarrierSetC2::write_ref_field_pre_Type(); + __ make_leaf_call(tf, CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre), "shenandoah_wb_pre", + pre_val, tls); } __ end_if(); // (!index) } __ end_if(); // (pre_val != nullptr) } __ end_if(); // (!marking) @@ -268,12 +269,12 @@ void ShenandoahBarrierSetC2::satb_write_barrier_pre(GraphKit* kit, bool ShenandoahBarrierSetC2::is_shenandoah_wb_pre_call(Node* call) { return call->is_CallLeaf() && - call->as_CallLeaf()->entry_point() == CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre_entry); + call->as_CallLeaf()->entry_point() == CAST_FROM_FN_PTR(address, ShenandoahRuntime::write_ref_field_pre); } bool ShenandoahBarrierSetC2::is_shenandoah_clone_call(Node* call) { return call->is_CallLeaf() && - call->as_CallLeaf()->entry_point() == CAST_FROM_FN_PTR(address, ShenandoahRuntime::shenandoah_clone_barrier); + call->as_CallLeaf()->entry_point() == CAST_FROM_FN_PTR(address, ShenandoahRuntime::clone_barrier); } bool ShenandoahBarrierSetC2::is_shenandoah_lrb_call(Node* call) { @@ -433,7 +434,7 @@ void ShenandoahBarrierSetC2::insert_pre_barrier(GraphKit* kit, Node* base_oop, N #undef __ -const TypeFunc* ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type() { +const TypeFunc* ShenandoahBarrierSetC2::write_ref_field_pre_Type() { const Type **fields = TypeTuple::fields(2); fields[TypeFunc::Parms+0] = TypeInstPtr::NOTNULL; // original field value fields[TypeFunc::Parms+1] = TypeRawPtr::NOTNULL; // thread @@ -446,7 +447,7 @@ const TypeFunc* ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type() { return TypeFunc::make(domain, range); } -const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type() { +const TypeFunc* ShenandoahBarrierSetC2::clone_barrier_Type() { const Type **fields = TypeTuple::fields(1); fields[TypeFunc::Parms+0] = TypeOopPtr::NOTNULL; // src oop const TypeTuple *domain = TypeTuple::make(TypeFunc::Parms+1, fields); @@ -458,7 +459,7 @@ const TypeFunc* ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type() { return TypeFunc::make(domain, range); } -const TypeFunc* ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type() { +const TypeFunc* ShenandoahBarrierSetC2::load_reference_barrier_Type() { const Type **fields = TypeTuple::fields(2); fields[TypeFunc::Parms+0] = TypeOopPtr::BOTTOM; // original field value fields[TypeFunc::Parms+1] = TypeRawPtr::BOTTOM; // original load address @@ -797,11 +798,11 @@ void ShenandoahBarrierSetC2::clone_at_expansion(PhaseMacroExpand* phase, ArrayCo // Heap is unstable, call into clone barrier stub Node* call = phase->make_leaf_call(unstable_ctrl, mem, - ShenandoahBarrierSetC2::shenandoah_clone_barrier_Type(), - CAST_FROM_FN_PTR(address, ShenandoahRuntime::shenandoah_clone_barrier), - "shenandoah_clone", - TypeRawPtr::BOTTOM, - src_base); + ShenandoahBarrierSetC2::clone_barrier_Type(), + CAST_FROM_FN_PTR(address, ShenandoahRuntime::clone_barrier), + "shenandoah_clone", + TypeRawPtr::BOTTOM, + src_base); call = phase->transform_later(call); ctrl = phase->transform_later(new ProjNode(call, TypeFunc::Control)); @@ -976,7 +977,7 @@ void ShenandoahBarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase p Node* ShenandoahBarrierSetC2::ideal_node(PhaseGVN* phase, Node* n, bool can_reshape) const { if (is_shenandoah_wb_pre_call(n)) { - uint cnt = ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type()->domain()->cnt(); + uint cnt = ShenandoahBarrierSetC2::write_ref_field_pre_Type()->domain()->cnt(); if (n->req() > cnt) { Node* addp = n->in(cnt); if (has_only_shenandoah_wb_pre_uses(addp)) { @@ -1062,7 +1063,7 @@ bool ShenandoahBarrierSetC2::final_graph_reshaping(Compile* compile, Node* n, ui assert (n->is_Call(), ""); CallNode *call = n->as_Call(); if (ShenandoahBarrierSetC2::is_shenandoah_wb_pre_call(call)) { - uint cnt = ShenandoahBarrierSetC2::write_ref_field_pre_entry_Type()->domain()->cnt(); + uint cnt = ShenandoahBarrierSetC2::write_ref_field_pre_Type()->domain()->cnt(); if (call->req() > cnt) { assert(call->req() == cnt + 1, "only one extra input"); Node *addp = call->in(cnt); diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp index cbfacea31ab7a..6e241b39ce967 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.hpp @@ -93,9 +93,9 @@ class ShenandoahBarrierSetC2 : public BarrierSetC2 { ShenandoahBarrierSetC2State* state() const; - static const TypeFunc* write_ref_field_pre_entry_Type(); - static const TypeFunc* shenandoah_clone_barrier_Type(); - static const TypeFunc* shenandoah_load_reference_barrier_Type(); + static const TypeFunc* write_ref_field_pre_Type(); + static const TypeFunc* clone_barrier_Type(); + static const TypeFunc* load_reference_barrier_Type(); virtual bool has_load_barrier_nodes() const { return true; } // This is the entry-point for the backend to perform accesses through the Access API. diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 7526f895f2f7f..efa0ced603cda 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -995,7 +995,7 @@ void ShenandoahBarrierC2Support::call_lrb_stub(Node*& ctrl, Node*& val, Node* lo name = "load_reference_barrier_phantom"; } } - Node* call = new CallLeafNode(ShenandoahBarrierSetC2::shenandoah_load_reference_barrier_Type(), calladdr, name, TypeRawPtr::BOTTOM); + Node* call = new CallLeafNode(ShenandoahBarrierSetC2::load_reference_barrier_Type(), calladdr, name, TypeRawPtr::BOTTOM); call->init_req(TypeFunc::Control, ctrl); call->init_req(TypeFunc::I_O, phase->C->top()); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp index 2c727de585799..b217c641824c2 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.cpp @@ -31,22 +31,19 @@ #include "oops/oop.inline.hpp" #include "utilities/copy.hpp" -void ShenandoahRuntime::arraycopy_barrier_oop_entry(oop* src, oop* dst, size_t length) { - ShenandoahBarrierSet *bs = ShenandoahBarrierSet::barrier_set(); - bs->arraycopy_barrier(src, dst, length); -} +JRT_LEAF(void, ShenandoahRuntime::arraycopy_barrier_oop(oop* src, oop* dst, size_t length)) + ShenandoahBarrierSet::barrier_set()->arraycopy_barrier(src, dst, length); +JRT_END -void ShenandoahRuntime::arraycopy_barrier_narrow_oop_entry(narrowOop* src, narrowOop* dst, size_t length) { - ShenandoahBarrierSet *bs = ShenandoahBarrierSet::barrier_set(); - bs->arraycopy_barrier(src, dst, length); -} +JRT_LEAF(void, ShenandoahRuntime::arraycopy_barrier_narrow_oop(narrowOop* src, narrowOop* dst, size_t length)) + ShenandoahBarrierSet::barrier_set()->arraycopy_barrier(src, dst, length); +JRT_END -// Shenandoah pre write barrier slowpath -JRT_LEAF(void, ShenandoahRuntime::write_ref_field_pre_entry(oopDesc* orig, JavaThread *thread)) +JRT_LEAF(void, ShenandoahRuntime::write_ref_field_pre(oopDesc * orig, JavaThread * thread)) assert(thread == JavaThread::current(), "pre-condition"); assert(orig != nullptr, "should be optimized out"); shenandoah_assert_correct(nullptr, orig); - // store the original value that was in the field reference + // Capture the original value that was in the field reference. assert(ShenandoahThreadLocalData::satb_mark_queue(thread).is_active(), "Shouldn't be here otherwise"); SATBMarkQueue& queue = ShenandoahThreadLocalData::satb_mark_queue(thread); ShenandoahBarrierSet::satb_mark_queue_set().enqueue_known_active(queue, orig); @@ -60,26 +57,24 @@ JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_strong_narrow(oopDe return ShenandoahBarrierSet::barrier_set()->load_reference_barrier_mutator(src, load_addr); JRT_END -// Shenandoah clone barrier: makes sure that references point to to-space -// in cloned objects. -JRT_LEAF(void, ShenandoahRuntime::shenandoah_clone_barrier(oopDesc* src)) - oop s = oop(src); - shenandoah_assert_correct(nullptr, s); - ShenandoahBarrierSet::barrier_set()->clone_barrier(s); -JRT_END - -JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_weak(oopDesc * src, oop* load_addr)) +JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_weak(oopDesc* src, oop* load_addr)) return (oopDesc*) ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_WEAK_OOP_REF, oop(src), load_addr); JRT_END -JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_weak_narrow(oopDesc * src, narrowOop* load_addr)) +JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_weak_narrow(oopDesc* src, narrowOop* load_addr)) return (oopDesc*) ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_WEAK_OOP_REF, oop(src), load_addr); JRT_END -JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_phantom(oopDesc * src, oop* load_addr)) +JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_phantom(oopDesc* src, oop* load_addr)) return (oopDesc*) ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_PHANTOM_OOP_REF, oop(src), load_addr); JRT_END -JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_phantom_narrow(oopDesc * src, narrowOop* load_addr)) +JRT_LEAF(oopDesc*, ShenandoahRuntime::load_reference_barrier_phantom_narrow(oopDesc* src, narrowOop* load_addr)) return (oopDesc*) ShenandoahBarrierSet::barrier_set()->load_reference_barrier(ON_PHANTOM_OOP_REF, oop(src), load_addr); JRT_END + +JRT_LEAF(void, ShenandoahRuntime::clone_barrier(oopDesc* src)) + oop s = oop(src); + shenandoah_assert_correct(nullptr, s); + ShenandoahBarrierSet::barrier_set()->clone_barrier(s); +JRT_END diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp index e187e4360b16b..4ad8fc997ea76 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp @@ -33,10 +33,10 @@ class oopDesc; class ShenandoahRuntime : public AllStatic { public: - static void arraycopy_barrier_oop_entry(oop* src, oop* dst, size_t length); - static void arraycopy_barrier_narrow_oop_entry(narrowOop* src, narrowOop* dst, size_t length); + static void arraycopy_barrier_oop(oop* src, oop* dst, size_t length); + static void arraycopy_barrier_narrow_oop(narrowOop* src, narrowOop* dst, size_t length); - static void write_ref_field_pre_entry(oopDesc* orig, JavaThread* thread); + static void write_ref_field_pre(oopDesc* orig, JavaThread* thread); static oopDesc* load_reference_barrier_strong(oopDesc* src, oop* load_addr); static oopDesc* load_reference_barrier_strong_narrow(oopDesc* src, narrowOop* load_addr); @@ -47,7 +47,7 @@ class ShenandoahRuntime : public AllStatic { static oopDesc* load_reference_barrier_phantom(oopDesc* src, oop* load_addr); static oopDesc* load_reference_barrier_phantom_narrow(oopDesc* src, narrowOop* load_addr); - static void shenandoah_clone_barrier(oopDesc* src); + static void clone_barrier(oopDesc* src); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHRUNTIME_HPP From 52ba72823be0c969ab873ead2863ec48f883210b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20L=C3=B6vdahl?= Date: Mon, 30 Sep 2024 08:33:12 +0000 Subject: [PATCH 07/15] 8327114: Attach in Linux may have wrong behaviour when pid == ns_pid (Kubernetes debug container) Co-authored-by: Larry Cable Reviewed-by: kevinw, sgehwolf --- .../sun/tools/attach/VirtualMachineImpl.java | 150 +++++++++++++----- .../docker/TestJcmdWithSideCar.java | 135 +++++++++++----- 2 files changed, 210 insertions(+), 75 deletions(-) diff --git a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java index 4eb29482e29ec..35ce808c18756 100644 --- a/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/linux/classes/sun/tools/attach/VirtualMachineImpl.java @@ -28,12 +28,13 @@ import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.spi.AttachProvider; -import java.io.InputStream; -import java.io.IOException; import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.nio.file.Files; +import java.util.Optional; import static java.nio.charset.StandardCharsets.UTF_8; @@ -47,13 +48,35 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine { // location is the same for all processes, otherwise the tools // will not be able to find all Hotspot processes. // Any changes to this needs to be synchronized with HotSpot. - private static final String tmpdir = "/tmp"; + private static final Path TMPDIR = Path.of("/tmp"); + + private static final Path PROC = Path.of("/proc"); + private static final Path NS_MNT = Path.of("ns/mnt"); + private static final Path NS_PID = Path.of("ns/pid"); + private static final Path SELF = PROC.resolve("self"); + private static final Path STATUS = Path.of("status"); + private static final Path ROOT_TMP = Path.of("root/tmp"); + + private static final Optional SELF_MNT_NS; + + static { + Path nsPath = null; + + try { + nsPath = Files.readSymbolicLink(SELF.resolve(NS_MNT)); + } catch (IOException _) { + // do nothing + } finally { + SELF_MNT_NS = Optional.ofNullable(nsPath); + } + } + String socket_path; + /** * Attaches to the target VM */ - VirtualMachineImpl(AttachProvider provider, String vmid) - throws AttachNotSupportedException, IOException + VirtualMachineImpl(AttachProvider provider, String vmid) throws AttachNotSupportedException, IOException { super(provider, vmid); @@ -64,12 +87,12 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine { } // Try to resolve to the "inner most" pid namespace - int ns_pid = getNamespacePid(pid); + final long ns_pid = getNamespacePid(pid); // Find the socket file. If not found then we attempt to start the // attach mechanism in the target VM by sending it a QUIT signal. // Then we attempt to find the socket file again. - File socket_file = findSocketFile(pid, ns_pid); + final File socket_file = findSocketFile(pid, ns_pid); socket_path = socket_file.getPath(); if (!socket_file.exists()) { // Keep canonical version of File, to delete, in case target process ends and /proc link has gone: @@ -211,49 +234,102 @@ protected void close(long fd) throws IOException { } // Return the socket file for the given process. - private File findSocketFile(int pid, int ns_pid) throws IOException { - String root = findTargetProcessTmpDirectory(pid, ns_pid); - return new File(root, ".java_pid" + ns_pid); + private File findSocketFile(long pid, long ns_pid) throws AttachNotSupportedException, IOException { + return new File(findTargetProcessTmpDirectory(pid, ns_pid), ".java_pid" + ns_pid); } // On Linux a simple handshake is used to start the attach mechanism // if not already started. The client creates a .attach_pid file in the // target VM's working directory (or temp directory), and the SIGQUIT handler // checks for the file. - private File createAttachFile(int pid, int ns_pid) throws IOException { - String fn = ".attach_pid" + ns_pid; - String path = "/proc/" + pid + "/cwd/" + fn; - File f = new File(path); + private File createAttachFile(long pid, long ns_pid) throws AttachNotSupportedException, IOException { + Path fn = Path.of(".attach_pid" + ns_pid); + Path path = PROC.resolve(Path.of(Long.toString(pid), "cwd")).resolve(fn); + File f = new File(path.toString()); try { // Do not canonicalize the file path, or we will fail to attach to a VM in a container. f.createNewFile(); - } catch (IOException x) { - String root = findTargetProcessTmpDirectory(pid, ns_pid); - f = new File(root, fn); + } catch (IOException _) { + f = new File(findTargetProcessTmpDirectory(pid, ns_pid), fn.toString()); f.createNewFile(); } return f; } - private String findTargetProcessTmpDirectory(int pid, int ns_pid) throws IOException { - String root; - if (pid != ns_pid) { - // A process may not exist in the same mount namespace as the caller, e.g. - // if we are trying to attach to a JVM process inside a container. - // Instead, attach relative to the target root filesystem as exposed by - // procfs regardless of namespaces. - String procRootDirectory = "/proc/" + pid + "/root"; - if (!Files.isReadable(Path.of(procRootDirectory))) { - throw new IOException( - String.format("Unable to access root directory %s " + - "of target process %d", procRootDirectory, pid)); + private String findTargetProcessTmpDirectory(long pid, long ns_pid) throws AttachNotSupportedException, IOException { + // We need to handle at least 4 different cases: + // 1. Caller and target processes share PID namespace and root filesystem (host to host or container to + // container with both /tmp mounted between containers). + // 2. Caller and target processes share PID namespace and root filesystem but the target process has elevated + // privileges (host to host). + // 3. Caller and target processes share PID namespace but NOT root filesystem (container to container). + // 4. Caller and target processes share neither PID namespace nor root filesystem (host to container). + + Optional target = ProcessHandle.of(pid); + Optional ph = target; + long nsPid = ns_pid; + Optional prevPidNS = Optional.empty(); + + while (ph.isPresent()) { + final var curPid = ph.get().pid(); + final var procPidPath = PROC.resolve(Long.toString(curPid)); + Optional targetMountNS = Optional.empty(); + + try { + // attempt to read the target's mnt ns id + targetMountNS = Optional.ofNullable(Files.readSymbolicLink(procPidPath.resolve(NS_MNT))); + } catch (IOException _) { + // if we fail to read the target's mnt ns id then we either don't have access or it no longer exists! + if (!Files.exists(procPidPath)) { + throw new IOException(String.format("unable to attach, %s non-existent! process: %d terminated", procPidPath, pid)); + } + // the process still exists, but we don't have privileges to read its procfs } - root = procRootDirectory + "/" + tmpdir; + final var sameMountNS = SELF_MNT_NS.isPresent() && SELF_MNT_NS.equals(targetMountNS); + + if (sameMountNS) { + return TMPDIR.toString(); // we share TMPDIR in common! + } else { + // we could not read the target's mnt ns + final var procPidRootTmp = procPidPath.resolve(ROOT_TMP); + if (Files.isReadable(procPidRootTmp)) { + return procPidRootTmp.toString(); // not in the same mnt ns but tmp is accessible via /proc + } + } + + // let's attempt to obtain the pid ns, best efforts to avoid crossing pid ns boundaries (as with a container) + Optional curPidNS = Optional.empty(); + + try { + // attempt to read the target's pid ns id + curPidNS = Optional.ofNullable(Files.readSymbolicLink(procPidPath.resolve(NS_PID))); + } catch (IOException _) { + // if we fail to read the target's pid ns id then we either don't have access or it no longer exists! + if (!Files.exists(procPidPath)) { + throw new IOException(String.format("unable to attach, %s non-existent! process: %d terminated", procPidPath, pid)); + } + // the process still exists, but we don't have privileges to read its procfs + } + + // recurse "up" the process hierarchy if appropriate. PID 1 cannot have a parent in the same namespace + final var havePidNSes = prevPidNS.isPresent() && curPidNS.isPresent(); + final var ppid = ph.get().parent(); + + if (ppid.isPresent() && (havePidNSes && curPidNS.equals(prevPidNS)) || (!havePidNSes && nsPid > 1)) { + ph = ppid; + nsPid = getNamespacePid(ph.get().pid()); // get the ns pid of the parent + prevPidNS = curPidNS; + } else { + ph = Optional.empty(); + } + } + + if (target.orElseThrow(AttachNotSupportedException::new).isAlive()) { + return TMPDIR.toString(); // fallback... } else { - root = tmpdir; + throw new IOException(String.format("unable to attach, process: %d terminated", pid)); } - return root; } /* @@ -270,13 +346,12 @@ private void writeString(int fd, String s) throws IOException { write(fd, b, 0, 1); } - // Return the inner most namespaced PID if there is one, // otherwise return the original PID. - private int getNamespacePid(int pid) throws AttachNotSupportedException, IOException { + private long getNamespacePid(long pid) throws AttachNotSupportedException, IOException { // Assuming a real procfs sits beneath, reading this doesn't block // nor will it consume a lot of memory. - String statusFile = "/proc/" + pid + "/status"; + final var statusFile = PROC.resolve(Long.toString(pid)).resolve(STATUS).toString(); File f = new File(statusFile); if (!f.exists()) { return pid; // Likely a bad pid, but this is properly handled later. @@ -292,8 +367,7 @@ private int getNamespacePid(int pid) throws AttachNotSupportedException, IOExcep // The last entry represents the PID the JVM "thinks" it is. // Even in non-namespaced pids these entries should be // valid. You could refer to it as the inner most pid. - int ns_pid = Integer.parseInt(parts[parts.length - 1]); - return ns_pid; + return Long.parseLong(parts[parts.length - 1]); } } // Old kernels may not have NSpid field (i.e. 3.10). diff --git a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java index 0aa16e8479bd2..2088398834702 100644 --- a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java +++ b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java @@ -38,12 +38,19 @@ * @build EventGeneratorLoop * @run driver TestJcmdWithSideCar */ +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; import java.nio.file.Paths; import java.util.Arrays; import java.util.ArrayList; +import java.util.Collections; +import java.util.EnumSet; import java.util.List; +import java.util.Optional; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; +import java.util.regex.Pattern; import java.util.stream.Collectors; import jdk.test.lib.Container; import jdk.test.lib.Utils; @@ -60,6 +67,31 @@ public class TestJcmdWithSideCar { private static final long TIME_TO_WAIT_FOR_MAIN_METHOD_START = 50 * 1000; // milliseconds private static final String MAIN_CONTAINER_NAME = "test-container-main"; + private static final String UID = "uid"; + private static final String GID = "gid"; + + private static final Pattern ID_PATTERN = Pattern.compile("uid=(?<" + UID + ">\\d+)\\([^\\)]+\\)\\s+gid=(?<" + GID + ">\\d+).*"); + + private static final Optional USER = ProcessHandle.current().info().user().map( + user -> { + try (var br = new BufferedReader(new InputStreamReader(new ProcessBuilder("id", user).start().getInputStream()))) { + for (final var line : br.lines().toList()) { + final var m = ID_PATTERN.matcher(line); + + if (m.matches()) { + return "--user=" + m.group(UID) + ":" + m.group(GID); + } + } + } catch (IOException e) { + // do nothing... + } + + return null; + } + ); + + private static final String NET_BIND_SERVICE = "--cap-add=NET_BIND_SERVICE"; + public static void main(String[] args) throws Exception { if (!DockerTestUtils.canTestDocker()) { return; @@ -68,24 +100,28 @@ public static void main(String[] args) throws Exception { DockerTestUtils.buildJdkContainerImage(IMAGE_NAME); try { - // Start the loop process in the "main" container, then run test cases - // using a sidecar container. - MainContainer mainContainer = new MainContainer(); - mainContainer.start(); - mainContainer.waitForMainMethodStart(TIME_TO_WAIT_FOR_MAIN_METHOD_START); - - long mainProcPid = testCase01(); - - // Excluding the test case below until JDK-8228850 is fixed - // JDK-8228850: jhsdb jinfo fails with ClassCastException: - // s.j.h.oops.TypeArray cannot be cast to s.j.h.oops.Instance - // mainContainer.assertIsAlive(); - // testCase02(mainProcPid); - - mainContainer.assertIsAlive(); - testCase03(mainProcPid); + for (final boolean elevated : USER.isPresent() ? new Boolean[] { false, true } : new Boolean[] { false }) { + // Start the loop process in the "main" container, then run test cases + // using a sidecar container. + MainContainer mainContainer = new MainContainer(); + mainContainer.start(elevated); + mainContainer.waitForMainMethodStart(TIME_TO_WAIT_FOR_MAIN_METHOD_START); + + for (AttachStrategy attachStrategy : EnumSet.allOf(AttachStrategy.class)) { + long mainProcPid = testCase01(attachStrategy, elevated); + + // Excluding the test case below until JDK-8228850 is fixed + // JDK-8228850: jhsdb jinfo fails with ClassCastException: + // s.j.h.oops.TypeArray cannot be cast to s.j.h.oops.Instance + // mainContainer.assertIsAlive(); + // testCase02(mainProcPid, attachStrategy, elevated); + + mainContainer.assertIsAlive(); + testCase03(mainProcPid, attachStrategy, elevated); + } - mainContainer.waitForAndCheck(TIME_TO_RUN_MAIN_PROCESS * 1000); + mainContainer.waitForAndCheck(TIME_TO_RUN_MAIN_PROCESS * 1000); + } } finally { DockerTestUtils.removeDockerImage(IMAGE_NAME); } @@ -93,21 +129,21 @@ public static void main(String[] args) throws Exception { // Run "jcmd -l" in a sidecar container, find a target process. - private static long testCase01() throws Exception { - OutputAnalyzer out = runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jcmd", "-l") + private static long testCase01(AttachStrategy attachStrategy, boolean elevated) throws Exception { + OutputAnalyzer out = runSideCar(MAIN_CONTAINER_NAME, attachStrategy, elevated, "/jdk/bin/jcmd", "-l") .shouldHaveExitValue(0) .shouldContain("sun.tools.jcmd.JCmd"); long pid = findProcess(out, "EventGeneratorLoop"); if (pid == -1) { - throw new RuntimeException("Could not find specified process"); + throw new RuntimeException(attachStrategy + ": Could not find specified process"); } return pid; } // run jhsdb jinfo (jhsdb uses PTRACE) - private static void testCase02(long pid) throws Exception { - runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jhsdb", "jinfo", "--pid", "" + pid) + private static void testCase02(long pid, AttachStrategy attachStrategy, boolean elevated) throws Exception { + runSideCar(MAIN_CONTAINER_NAME, attachStrategy, elevated, "/jdk/bin/jhsdb", "jinfo", "--pid", "" + pid) .shouldHaveExitValue(0) .shouldContain("Java System Properties") .shouldContain("VM Flags"); @@ -115,11 +151,11 @@ private static void testCase02(long pid) throws Exception { // test jcmd with some commands (help, start JFR recording) // JCMD will use signal mechanism and Unix Socket - private static void testCase03(long pid) throws Exception { - runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jcmd", "" + pid, "help") + private static void testCase03(long pid, AttachStrategy attachStrategy, boolean elevated) throws Exception { + runSideCar(MAIN_CONTAINER_NAME, attachStrategy, elevated, "/jdk/bin/jcmd", "" + pid, "help") .shouldHaveExitValue(0) .shouldContain("VM.version"); - runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jcmd", "" + pid, "JFR.start") + runSideCar(MAIN_CONTAINER_NAME, attachStrategy, elevated, "/jdk/bin/jcmd", "" + pid, "JFR.start") .shouldHaveExitValue(0) .shouldContain("Started recording"); } @@ -127,21 +163,36 @@ private static void testCase03(long pid) throws Exception { // JCMD relies on the attach mechanism (com.sun.tools.attach), // which in turn relies on JVMSTAT mechanism, which puts its mapped - // buffers in /tmp directory (hsperfdata_). Thus, in sidecar - // we mount /tmp via --volumes-from from the main container. - private static OutputAnalyzer runSideCar(String mainContainerName, String whatToRun, - String... args) throws Exception { - List cmd = new ArrayList<>(); - String[] command = new String[] { + // buffers in /tmp directory (hsperfdata_). Thus, in the sidecar + // we have two options: + // 1. mount /tmp from the main container using --volumes-from. + // 2. access /tmp from the main container via /proc//root/tmp. + private static OutputAnalyzer runSideCar(String mainContainerName, AttachStrategy attachStrategy, boolean elevated, String whatToRun, String... args) throws Exception { + System.out.println("Attach strategy " + attachStrategy); + + List initialCommands = List.of( Container.ENGINE_COMMAND, "run", "--tty=true", "--rm", "--cap-add=SYS_PTRACE", "--sig-proxy=true", - "--pid=container:" + mainContainerName, - "--volumes-from", mainContainerName, - IMAGE_NAME, whatToRun + "--pid=container:" + mainContainerName + ); + + List attachStrategyCommands = switch (attachStrategy) { + case TMP_MOUNTED_INTO_SIDECAR -> List.of("--volumes-from", mainContainerName); + case ACCESS_TMP_VIA_PROC_ROOT -> List.of(); }; - cmd.addAll(Arrays.asList(command)); + List elevatedOpts = elevated && USER.isPresent() ? List.of(NET_BIND_SERVICE, USER.get()) : Collections.emptyList(); + + List imageAndCommand = List.of( + IMAGE_NAME, whatToRun + ); + + List cmd = new ArrayList<>(); + cmd.addAll(initialCommands); + cmd.addAll(elevatedOpts); + cmd.addAll(attachStrategyCommands); + cmd.addAll(imageAndCommand); cmd.addAll(Arrays.asList(args)); return DockerTestUtils.execute(cmd); } @@ -188,9 +239,15 @@ static class MainContainer { } }; - public Process start() throws Exception { + public Process start(final boolean elevated) throws Exception { // start "main" container (the observee) DockerRunOptions opts = commonDockerOpts("EventGeneratorLoop"); + + if (elevated && USER.isPresent()) { + opts.addDockerOpts(USER.get()); + opts.addDockerOpts(NET_BIND_SERVICE); + } + opts.addDockerOpts("--cap-add=SYS_PTRACE") .addDockerOpts("--name", MAIN_CONTAINER_NAME) .addDockerOpts("--volume", "/tmp") @@ -241,7 +298,7 @@ public void waitForAndCheck(long timeout) throws Exception { try { exitValue = p.exitValue(); } catch(IllegalThreadStateException ex) { - System.out.println("IllegalThreadStateException occured when calling exitValue()"); + System.out.println("IllegalThreadStateException occurred when calling exitValue()"); retryCount--; } } while (exitValue == -1 && retryCount > 0); @@ -253,4 +310,8 @@ public void waitForAndCheck(long timeout) throws Exception { } + private enum AttachStrategy { + TMP_MOUNTED_INTO_SIDECAR, + ACCESS_TMP_VIA_PROC_ROOT + } } From 475b8943c672349609a4839ce0a02ef995764698 Mon Sep 17 00:00:00 2001 From: Mikhail Ablakatov <164922675+mikabl-arm@users.noreply.github.com> Date: Mon, 30 Sep 2024 09:02:59 +0000 Subject: [PATCH 08/15] 8322770: Implement C2 VectorizedHashCode on AArch64 Reviewed-by: aph, adinn --- src/hotspot/cpu/aarch64/aarch64.ad | 78 ++ src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 68 +- .../cpu/aarch64/c2_MacroAssembler_aarch64.cpp | 91 ++ .../cpu/aarch64/c2_MacroAssembler_aarch64.hpp | 3 + .../cpu/aarch64/stubGenerator_aarch64.cpp | 312 +++++ .../cpu/aarch64/stubRoutines_aarch64.cpp | 7 +- .../cpu/aarch64/stubRoutines_aarch64.hpp | 26 +- .../cpu/aarch64/vm_version_aarch64.cpp | 4 + src/hotspot/share/utilities/intpow.hpp | 46 + test/hotspot/gtest/aarch64/aarch64-asmtest.py | 111 ++ test/hotspot/gtest/aarch64/asmtest.out.h | 1189 +++++++++-------- 11 files changed, 1355 insertions(+), 580 deletions(-) create mode 100644 src/hotspot/share/utilities/intpow.hpp diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 39eae43a287e7..0a93c27c2686b 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -4931,6 +4931,60 @@ operand vRegD_V7() interface(REG_INTER); %} +operand vRegD_V12() +%{ + constraint(ALLOC_IN_RC(v12_reg)); + match(RegD); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vRegD_V13() +%{ + constraint(ALLOC_IN_RC(v13_reg)); + match(RegD); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vRegD_V14() +%{ + constraint(ALLOC_IN_RC(v14_reg)); + match(RegD); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vRegD_V15() +%{ + constraint(ALLOC_IN_RC(v15_reg)); + match(RegD); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vRegD_V16() +%{ + constraint(ALLOC_IN_RC(v16_reg)); + match(RegD); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + +operand vRegD_V17() +%{ + constraint(ALLOC_IN_RC(v17_reg)); + match(RegD); + op_cost(0); + format %{ %} + interface(REG_INTER); +%} + operand pReg() %{ constraint(ALLOC_IN_RC(pr_reg)); @@ -16551,6 +16605,30 @@ instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, ins_pipe(pipe_class_memory); %} +instruct arrays_hashcode(iRegP_R1 ary, iRegI_R2 cnt, iRegI_R0 result, immI basic_type, + vRegD_V0 vtmp0, vRegD_V1 vtmp1, vRegD_V2 vtmp2, vRegD_V3 vtmp3, + vRegD_V4 vtmp4, vRegD_V5 vtmp5, vRegD_V6 vtmp6, vRegD_V7 vtmp7, + vRegD_V12 vtmp8, vRegD_V13 vtmp9, vRegD_V14 vtmp10, + vRegD_V15 vtmp11, vRegD_V16 vtmp12, vRegD_V17 vtmp13, + rFlagsReg cr) +%{ + match(Set result (VectorizedHashCode (Binary ary cnt) (Binary result basic_type))); + effect(TEMP vtmp0, TEMP vtmp1, TEMP vtmp2, TEMP vtmp3, TEMP vtmp4, TEMP vtmp5, TEMP vtmp6, + TEMP vtmp7, TEMP vtmp8, TEMP vtmp9, TEMP vtmp10, TEMP vtmp11, TEMP vtmp12, TEMP vtmp13, + USE_KILL ary, USE_KILL cnt, USE basic_type, KILL cr); + + format %{ "Array HashCode array[] $ary,$cnt,$result,$basic_type -> $result // KILL all" %} + ins_encode %{ + address tpc = __ arrays_hashcode($ary$$Register, $cnt$$Register, $result$$Register, + (BasicType)$basic_type$$constant); + if (tpc == nullptr) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } + %} + ins_pipe(pipe_class_memory); +%} + instruct count_positives(iRegP_R1 ary1, iRegI_R2 len, iRegI_R0 result, rFlagsReg cr) %{ match(Set result (CountPositives ary1 len)); diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index 28a0cc2c7d940..a5e0e2665af92 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2024, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -287,6 +287,11 @@ class Instruction_aarch64 { f(r->raw_encoding(), lsb + 4, lsb); } + //<0-15>reg: As `rf(FloatRegister)`, but only the lower 16 FloatRegisters are allowed. + void lrf(FloatRegister r, int lsb) { + f(r->raw_encoding(), lsb + 3, lsb); + } + void prf(PRegister r, int lsb) { f(r->raw_encoding(), lsb + 3, lsb); } @@ -765,6 +770,7 @@ class Assembler : public AbstractAssembler { #define f current_insn.f #define sf current_insn.sf #define rf current_insn.rf +#define lrf current_insn.lrf #define srf current_insn.srf #define zrf current_insn.zrf #define prf current_insn.prf @@ -1590,6 +1596,16 @@ class Assembler : public AbstractAssembler { #undef INSN + // Load/store a register, but with a BasicType parameter. Loaded signed integer values are + // extended to 64 bits. + void load(Register Rt, const Address &adr, BasicType bt) { + int op = (is_signed_subword_type(bt) || bt == T_INT) ? 0b10 : 0b01; + ld_st2(Rt, adr, exact_log2(type2aelembytes(bt)), op); + } + void store(Register Rt, const Address &adr, BasicType bt) { + ld_st2(Rt, adr, exact_log2(type2aelembytes(bt)), 0b00); + } + /* SIMD extensions * * We just use FloatRegister in the following. They are exactly the same @@ -2587,6 +2603,7 @@ template INSN(addpv, 0, 0b101111, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D INSN(smullv, 0, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(umullv, 1, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S + INSN(smlalv, 0, 0b100000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(umlalv, 1, 0b100000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(maxv, 0, 0b011001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(minv, 0, 0b011011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S @@ -2860,6 +2877,28 @@ template // FMULX - Vector - Scalar INSN(fmulxvs, 1, 0b1001); +#undef INSN + +#define INSN(NAME, op1, op2) \ + void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm, int index) { \ + starti; \ + assert(T == T4H || T == T8H || T == T2S || T == T4S, "invalid arrangement"); \ + assert(index >= 0 && \ + ((T == T2S && index <= 1) || (T != T2S && index <= 3) || (T == T8H && index <= 7)), \ + "invalid index"); \ + assert((T != T4H && T != T8H) || Vm->encoding() < 16, "invalid source SIMD&FP register"); \ + f(0, 31), f((int)T & 1, 30), f(op1, 29), f(0b01111, 28, 24); \ + if (T == T4H || T == T8H) { \ + f(0b01, 23, 22), f(index & 0b11, 21, 20), lrf(Vm, 16), f(index >> 2 & 1, 11); \ + } else { \ + f(0b10, 23, 22), f(index & 1, 21), rf(Vm, 16), f(index >> 1, 11); \ + } \ + f(op2, 15, 12), f(0, 10), rf(Vn, 5), rf(Vd, 0); \ + } + + // MUL - Vector - Scalar + INSN(mulvs, 0, 0b1000); + #undef INSN // Floating-point Reciprocal Estimate @@ -3023,6 +3062,33 @@ template umov(Xd, Vn, T, index); } + protected: + void _xaddwv(bool is_unsigned, FloatRegister Vd, FloatRegister Vn, SIMD_Arrangement Ta, + FloatRegister Vm, SIMD_Arrangement Tb) { + starti; + assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement"); + f(0, 31), f((int)Tb & 1, 30), f(is_unsigned ? 1 : 0, 29), f(0b01110, 28, 24); + f((int)(Ta >> 1) - 1, 23, 22), f(1, 21), rf(Vm, 16), f(0b000100, 15, 10), rf(Vn, 5), rf(Vd, 0); + } + + public: +#define INSN(NAME, assertion, is_unsigned) \ + void NAME(FloatRegister Vd, FloatRegister Vn, SIMD_Arrangement Ta, FloatRegister Vm, \ + SIMD_Arrangement Tb) { \ + assert((assertion), "invalid arrangement"); \ + _xaddwv(is_unsigned, Vd, Vn, Ta, Vm, Tb); \ + } + +public: + + INSN(uaddwv, Tb == T8B || Tb == T4H || Tb == T2S, /*is_unsigned*/true) + INSN(uaddwv2, Tb == T16B || Tb == T8H || Tb == T4S, /*is_unsigned*/true) + INSN(saddwv, Tb == T8B || Tb == T4H || Tb == T2S, /*is_unsigned*/false) + INSN(saddwv2, Tb == T16B || Tb == T8H || Tb == T4S, /*is_unsigned*/false) + +#undef INSN + + private: void _pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) { starti; diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index b4c12ecd4a849..ab2bd7d782c04 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -33,6 +33,7 @@ #include "opto/subnode.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/powerOfTwo.hpp" #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -46,6 +47,96 @@ typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr); +// jdk.internal.util.ArraysSupport.vectorizedHashCode +address C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register result, + BasicType eltype) { + assert_different_registers(ary, cnt, result, rscratch1, rscratch2); + + Register tmp1 = rscratch1, tmp2 = rscratch2; + + Label TAIL, STUB_SWITCH, STUB_SWITCH_OUT, LOOP, BR_BASE, LARGE, DONE; + + // Vectorization factor. Number of array elements loaded to one SIMD&FP registers by the stubs. We + // use 8H load arrangements for chars and shorts and 8B for booleans and bytes. It's possible to + // use 4H for chars and shorts instead, but using 8H gives better performance. + const size_t vf = eltype == T_BOOLEAN || eltype == T_BYTE ? 8 + : eltype == T_CHAR || eltype == T_SHORT ? 8 + : eltype == T_INT ? 4 + : 0; + guarantee(vf, "unsupported eltype"); + + // Unroll factor for the scalar loop below. The value is chosen based on performance analysis. + const size_t unroll_factor = 4; + + switch (eltype) { + case T_BOOLEAN: + BLOCK_COMMENT("arrays_hashcode(unsigned byte) {"); + break; + case T_CHAR: + BLOCK_COMMENT("arrays_hashcode(char) {"); + break; + case T_BYTE: + BLOCK_COMMENT("arrays_hashcode(byte) {"); + break; + case T_SHORT: + BLOCK_COMMENT("arrays_hashcode(short) {"); + break; + case T_INT: + BLOCK_COMMENT("arrays_hashcode(int) {"); + break; + default: + ShouldNotReachHere(); + } + + // large_arrays_hashcode(T_INT) performs worse than the scalar loop below when the Neon loop + // implemented by the stub executes just once. Call the stub only if at least two iterations will + // be executed. + const size_t large_threshold = eltype == T_INT ? vf * 2 : vf; + cmpw(cnt, large_threshold); + br(Assembler::HS, LARGE); + + bind(TAIL); + + // The andr performs cnt % uf where uf = unroll_factor. The subtract shifted by 3 offsets past + // uf - (cnt % uf) pairs of load + madd insns i.e. it only executes cnt % uf load + madd pairs. + // Iteration eats up the remainder, uf elements at a time. + assert(is_power_of_2(unroll_factor), "can't use this value to calculate the jump target PC"); + andr(tmp2, cnt, unroll_factor - 1); + adr(tmp1, BR_BASE); + sub(tmp1, tmp1, tmp2, ext::sxtw, 3); + movw(tmp2, 0x1f); + br(tmp1); + + bind(LOOP); + for (size_t i = 0; i < unroll_factor; ++i) { + load(tmp1, Address(post(ary, type2aelembytes(eltype))), eltype); + maddw(result, result, tmp2, tmp1); + } + bind(BR_BASE); + subsw(cnt, cnt, unroll_factor); + br(Assembler::HS, LOOP); + + b(DONE); + + bind(LARGE); + + RuntimeAddress stub = RuntimeAddress(StubRoutines::aarch64::large_arrays_hashcode(eltype)); + assert(stub.target() != nullptr, "array_hashcode stub has not been generated"); + address tpc = trampoline_call(stub); + if (tpc == nullptr) { + DEBUG_ONLY(reset_labels(TAIL, BR_BASE)); + postcond(pc() == badAddress); + return nullptr; + } + + bind(DONE); + + BLOCK_COMMENT("} // arrays_hashcode"); + + postcond(pc() != badAddress); + return pc(); +} + void C2_MacroAssembler::fast_lock(Register objectReg, Register boxReg, Register tmpReg, Register tmp2Reg, Register tmp3Reg) { Register oop = objectReg; diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp index 43e60ae5a48f8..28cc401a1b2c8 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp @@ -35,6 +35,9 @@ enum shift_kind kind = Assembler::LSL, unsigned shift = 0); public: + // jdk.internal.util.ArraysSupport.vectorizedHashCode + address arrays_hashcode(Register ary, Register cnt, Register result, BasicType eltype); + // Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file. void fast_lock(Register object, Register box, Register tmp, Register tmp2, Register tmp3); void fast_unlock(Register object, Register box, Register tmp, Register tmp2); diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index b3513a586de35..ac88b427459c0 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -53,7 +53,9 @@ #include "runtime/stubRoutines.hpp" #include "utilities/align.hpp" #include "utilities/checkedCast.hpp" +#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/intpow.hpp" #include "utilities/powerOfTwo.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" @@ -5311,6 +5313,309 @@ class StubGenerator: public StubCodeGenerator { return entry; } + // result = r0 - return value. Contains initial hashcode value on entry. + // ary = r1 - array address + // cnt = r2 - elements count + // Clobbers: v0-v13, rscratch1, rscratch2 + address generate_large_arrays_hashcode(BasicType eltype) { + const Register result = r0, ary = r1, cnt = r2; + const FloatRegister vdata0 = v3, vdata1 = v2, vdata2 = v1, vdata3 = v0; + const FloatRegister vmul0 = v4, vmul1 = v5, vmul2 = v6, vmul3 = v7; + const FloatRegister vpow = v8; // powers of 31: <31^3, ..., 31^0> + const FloatRegister vpowm = v9; + + assert_different_registers(ary, cnt, result); + assert_different_registers(vdata0, vdata1, vdata2, vdata3, vmul0, vmul1, vmul2, vmul3, vpow, + vpowm); + + Label SMALL_LOOP, LARGE_LOOP_PREHEADER, LARGE_LOOP, TAIL, TAIL_SHORTCUT, BR_BASE; + + unsigned int vf; // vectorization factor + bool multiply_by_halves; + Assembler::SIMD_Arrangement load_arrangement; + switch (eltype) { + case T_BOOLEAN: + case T_BYTE: + load_arrangement = Assembler::T8B; + multiply_by_halves = true; + vf = 8; + break; + case T_CHAR: + case T_SHORT: + load_arrangement = Assembler::T8H; + multiply_by_halves = true; + vf = 8; + break; + case T_INT: + load_arrangement = Assembler::T4S; + multiply_by_halves = false; + vf = 4; + break; + default: + ShouldNotReachHere(); + } + + // Unroll factor + const unsigned uf = 4; + + // Effective vectorization factor + const unsigned evf = vf * uf; + + __ align(CodeEntryAlignment); + + const char *mark_name = ""; + switch (eltype) { + case T_BOOLEAN: + mark_name = "_large_arrays_hashcode_boolean"; + break; + case T_BYTE: + mark_name = "_large_arrays_hashcode_byte"; + break; + case T_CHAR: + mark_name = "_large_arrays_hashcode_char"; + break; + case T_SHORT: + mark_name = "_large_arrays_hashcode_short"; + break; + case T_INT: + mark_name = "_large_arrays_hashcode_int"; + break; + default: + mark_name = "_large_arrays_hashcode_incorrect_type"; + __ should_not_reach_here(); + }; + + StubCodeMark mark(this, "StubRoutines", mark_name); + + address entry = __ pc(); + __ enter(); + + // Put 0-3'th powers of 31 into a single SIMD register together. The register will be used in + // the SMALL and LARGE LOOPS' epilogues. The initialization is hoisted here and the register's + // value shouldn't change throughout both loops. + __ movw(rscratch1, intpow(31U, 3)); + __ mov(vpow, Assembler::S, 0, rscratch1); + __ movw(rscratch1, intpow(31U, 2)); + __ mov(vpow, Assembler::S, 1, rscratch1); + __ movw(rscratch1, intpow(31U, 1)); + __ mov(vpow, Assembler::S, 2, rscratch1); + __ movw(rscratch1, intpow(31U, 0)); + __ mov(vpow, Assembler::S, 3, rscratch1); + + __ mov(vmul0, Assembler::T16B, 0); + __ mov(vmul0, Assembler::S, 3, result); + + __ andr(rscratch2, cnt, (uf - 1) * vf); + __ cbz(rscratch2, LARGE_LOOP_PREHEADER); + + __ movw(rscratch1, intpow(31U, multiply_by_halves ? vf / 2 : vf)); + __ mov(vpowm, Assembler::S, 0, rscratch1); + + // SMALL LOOP + __ bind(SMALL_LOOP); + + __ ld1(vdata0, load_arrangement, Address(__ post(ary, vf * type2aelembytes(eltype)))); + __ mulvs(vmul0, Assembler::T4S, vmul0, vpowm, 0); + __ subsw(rscratch2, rscratch2, vf); + + if (load_arrangement == Assembler::T8B) { + // Extend 8B to 8H to be able to use vector multiply + // instructions + assert(load_arrangement == Assembler::T8B, "expected to extend 8B to 8H"); + if (is_signed_subword_type(eltype)) { + __ sxtl(vdata0, Assembler::T8H, vdata0, load_arrangement); + } else { + __ uxtl(vdata0, Assembler::T8H, vdata0, load_arrangement); + } + } + + switch (load_arrangement) { + case Assembler::T4S: + __ addv(vmul0, load_arrangement, vmul0, vdata0); + break; + case Assembler::T8B: + case Assembler::T8H: + assert(is_subword_type(eltype), "subword type expected"); + if (is_signed_subword_type(eltype)) { + __ saddwv(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T4H); + } else { + __ uaddwv(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T4H); + } + break; + default: + __ should_not_reach_here(); + } + + // Process the upper half of a vector + if (load_arrangement == Assembler::T8B || load_arrangement == Assembler::T8H) { + __ mulvs(vmul0, Assembler::T4S, vmul0, vpowm, 0); + if (is_signed_subword_type(eltype)) { + __ saddwv2(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T8H); + } else { + __ uaddwv2(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T8H); + } + } + + __ br(Assembler::HI, SMALL_LOOP); + + // SMALL LOOP'S EPILOQUE + __ lsr(rscratch2, cnt, exact_log2(evf)); + __ cbnz(rscratch2, LARGE_LOOP_PREHEADER); + + __ mulv(vmul0, Assembler::T4S, vmul0, vpow); + __ addv(vmul0, Assembler::T4S, vmul0); + __ umov(result, vmul0, Assembler::S, 0); + + // TAIL + __ bind(TAIL); + + // The andr performs cnt % vf. The subtract shifted by 3 offsets past vf - 1 - (cnt % vf) pairs + // of load + madd insns i.e. it only executes cnt % vf load + madd pairs. + assert(is_power_of_2(vf), "can't use this value to calculate the jump target PC"); + __ andr(rscratch2, cnt, vf - 1); + __ bind(TAIL_SHORTCUT); + __ adr(rscratch1, BR_BASE); + __ sub(rscratch1, rscratch1, rscratch2, ext::uxtw, 3); + __ movw(rscratch2, 0x1f); + __ br(rscratch1); + + for (size_t i = 0; i < vf - 1; ++i) { + __ load(rscratch1, Address(__ post(ary, type2aelembytes(eltype))), + eltype); + __ maddw(result, result, rscratch2, rscratch1); + } + __ bind(BR_BASE); + + __ leave(); + __ ret(lr); + + // LARGE LOOP + __ bind(LARGE_LOOP_PREHEADER); + + __ lsr(rscratch2, cnt, exact_log2(evf)); + + if (multiply_by_halves) { + // 31^4 - multiplier between lower and upper parts of a register + __ movw(rscratch1, intpow(31U, vf / 2)); + __ mov(vpowm, Assembler::S, 1, rscratch1); + // 31^28 - remainder of the iteraion multiplier, 28 = 32 - 4 + __ movw(rscratch1, intpow(31U, evf - vf / 2)); + __ mov(vpowm, Assembler::S, 0, rscratch1); + } else { + // 31^16 + __ movw(rscratch1, intpow(31U, evf)); + __ mov(vpowm, Assembler::S, 0, rscratch1); + } + + __ mov(vmul3, Assembler::T16B, 0); + __ mov(vmul2, Assembler::T16B, 0); + __ mov(vmul1, Assembler::T16B, 0); + + __ bind(LARGE_LOOP); + + __ mulvs(vmul3, Assembler::T4S, vmul3, vpowm, 0); + __ mulvs(vmul2, Assembler::T4S, vmul2, vpowm, 0); + __ mulvs(vmul1, Assembler::T4S, vmul1, vpowm, 0); + __ mulvs(vmul0, Assembler::T4S, vmul0, vpowm, 0); + + __ ld1(vdata3, vdata2, vdata1, vdata0, load_arrangement, + Address(__ post(ary, evf * type2aelembytes(eltype)))); + + if (load_arrangement == Assembler::T8B) { + // Extend 8B to 8H to be able to use vector multiply + // instructions + assert(load_arrangement == Assembler::T8B, "expected to extend 8B to 8H"); + if (is_signed_subword_type(eltype)) { + __ sxtl(vdata3, Assembler::T8H, vdata3, load_arrangement); + __ sxtl(vdata2, Assembler::T8H, vdata2, load_arrangement); + __ sxtl(vdata1, Assembler::T8H, vdata1, load_arrangement); + __ sxtl(vdata0, Assembler::T8H, vdata0, load_arrangement); + } else { + __ uxtl(vdata3, Assembler::T8H, vdata3, load_arrangement); + __ uxtl(vdata2, Assembler::T8H, vdata2, load_arrangement); + __ uxtl(vdata1, Assembler::T8H, vdata1, load_arrangement); + __ uxtl(vdata0, Assembler::T8H, vdata0, load_arrangement); + } + } + + switch (load_arrangement) { + case Assembler::T4S: + __ addv(vmul3, load_arrangement, vmul3, vdata3); + __ addv(vmul2, load_arrangement, vmul2, vdata2); + __ addv(vmul1, load_arrangement, vmul1, vdata1); + __ addv(vmul0, load_arrangement, vmul0, vdata0); + break; + case Assembler::T8B: + case Assembler::T8H: + assert(is_subword_type(eltype), "subword type expected"); + if (is_signed_subword_type(eltype)) { + __ saddwv(vmul3, vmul3, Assembler::T4S, vdata3, Assembler::T4H); + __ saddwv(vmul2, vmul2, Assembler::T4S, vdata2, Assembler::T4H); + __ saddwv(vmul1, vmul1, Assembler::T4S, vdata1, Assembler::T4H); + __ saddwv(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T4H); + } else { + __ uaddwv(vmul3, vmul3, Assembler::T4S, vdata3, Assembler::T4H); + __ uaddwv(vmul2, vmul2, Assembler::T4S, vdata2, Assembler::T4H); + __ uaddwv(vmul1, vmul1, Assembler::T4S, vdata1, Assembler::T4H); + __ uaddwv(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T4H); + } + break; + default: + __ should_not_reach_here(); + } + + // Process the upper half of a vector + if (load_arrangement == Assembler::T8B || load_arrangement == Assembler::T8H) { + __ mulvs(vmul3, Assembler::T4S, vmul3, vpowm, 1); + __ mulvs(vmul2, Assembler::T4S, vmul2, vpowm, 1); + __ mulvs(vmul1, Assembler::T4S, vmul1, vpowm, 1); + __ mulvs(vmul0, Assembler::T4S, vmul0, vpowm, 1); + if (is_signed_subword_type(eltype)) { + __ saddwv2(vmul3, vmul3, Assembler::T4S, vdata3, Assembler::T8H); + __ saddwv2(vmul2, vmul2, Assembler::T4S, vdata2, Assembler::T8H); + __ saddwv2(vmul1, vmul1, Assembler::T4S, vdata1, Assembler::T8H); + __ saddwv2(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T8H); + } else { + __ uaddwv2(vmul3, vmul3, Assembler::T4S, vdata3, Assembler::T8H); + __ uaddwv2(vmul2, vmul2, Assembler::T4S, vdata2, Assembler::T8H); + __ uaddwv2(vmul1, vmul1, Assembler::T4S, vdata1, Assembler::T8H); + __ uaddwv2(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T8H); + } + } + + __ subsw(rscratch2, rscratch2, 1); + __ br(Assembler::HI, LARGE_LOOP); + + __ mulv(vmul3, Assembler::T4S, vmul3, vpow); + __ addv(vmul3, Assembler::T4S, vmul3); + __ umov(result, vmul3, Assembler::S, 0); + + __ mov(rscratch2, intpow(31U, vf)); + + __ mulv(vmul2, Assembler::T4S, vmul2, vpow); + __ addv(vmul2, Assembler::T4S, vmul2); + __ umov(rscratch1, vmul2, Assembler::S, 0); + __ maddw(result, result, rscratch2, rscratch1); + + __ mulv(vmul1, Assembler::T4S, vmul1, vpow); + __ addv(vmul1, Assembler::T4S, vmul1); + __ umov(rscratch1, vmul1, Assembler::S, 0); + __ maddw(result, result, rscratch2, rscratch1); + + __ mulv(vmul0, Assembler::T4S, vmul0, vpow); + __ addv(vmul0, Assembler::T4S, vmul0); + __ umov(rscratch1, vmul0, Assembler::S, 0); + __ maddw(result, result, rscratch2, rscratch1); + + __ andr(rscratch2, cnt, vf - 1); + __ cbnz(rscratch2, TAIL_SHORTCUT); + + __ leave(); + __ ret(lr); + + return entry; + } + address generate_dsin_dcos(bool isCos) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", isCos ? "libmDcos" : "libmDsin"); @@ -8257,6 +8562,13 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::aarch64::_large_array_equals = generate_large_array_equals(); } + // arrays_hascode stub for large arrays. + StubRoutines::aarch64::_large_arrays_hashcode_boolean = generate_large_arrays_hashcode(T_BOOLEAN); + StubRoutines::aarch64::_large_arrays_hashcode_byte = generate_large_arrays_hashcode(T_BYTE); + StubRoutines::aarch64::_large_arrays_hashcode_char = generate_large_arrays_hashcode(T_CHAR); + StubRoutines::aarch64::_large_arrays_hashcode_int = generate_large_arrays_hashcode(T_INT); + StubRoutines::aarch64::_large_arrays_hashcode_short = generate_large_arrays_hashcode(T_SHORT); + // byte_array_inflate stub for large arrays. StubRoutines::aarch64::_large_byte_array_inflate = generate_large_byte_array_inflate(); diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp index 80875a3b3cdcf..dee615df5a51f 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -48,6 +48,11 @@ address StubRoutines::aarch64::_zero_blocks = nullptr; address StubRoutines::aarch64::_count_positives = nullptr; address StubRoutines::aarch64::_count_positives_long = nullptr; address StubRoutines::aarch64::_large_array_equals = nullptr; +address StubRoutines::aarch64::_large_arrays_hashcode_boolean = nullptr; +address StubRoutines::aarch64::_large_arrays_hashcode_byte = nullptr; +address StubRoutines::aarch64::_large_arrays_hashcode_char = nullptr; +address StubRoutines::aarch64::_large_arrays_hashcode_int = nullptr; +address StubRoutines::aarch64::_large_arrays_hashcode_short = nullptr; address StubRoutines::aarch64::_compare_long_string_LL = nullptr; address StubRoutines::aarch64::_compare_long_string_UU = nullptr; address StubRoutines::aarch64::_compare_long_string_LU = nullptr; diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp index e6438908ce4c6..7d3b72a88363d 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -62,6 +62,11 @@ class aarch64 { static address _zero_blocks; static address _large_array_equals; + static address _large_arrays_hashcode_boolean; + static address _large_arrays_hashcode_byte; + static address _large_arrays_hashcode_char; + static address _large_arrays_hashcode_int; + static address _large_arrays_hashcode_short; static address _compare_long_string_LL; static address _compare_long_string_LU; static address _compare_long_string_UL; @@ -145,6 +150,25 @@ class aarch64 { return _large_array_equals; } + static address large_arrays_hashcode(BasicType eltype) { + switch (eltype) { + case T_BOOLEAN: + return _large_arrays_hashcode_boolean; + case T_BYTE: + return _large_arrays_hashcode_byte; + case T_CHAR: + return _large_arrays_hashcode_char; + case T_SHORT: + return _large_arrays_hashcode_short; + case T_INT: + return _large_arrays_hashcode_int; + default: + ShouldNotReachHere(); + } + + return nullptr; + } + static address compare_long_string_LL() { return _compare_long_string_LL; } diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index d71162ac568ea..81e39113afaab 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -574,6 +574,10 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UsePoly1305Intrinsics)) { FLAG_SET_DEFAULT(UsePoly1305Intrinsics, true); } + + if (FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) { + FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, true); + } #endif _spin_wait = get_spin_wait_desc(); diff --git a/src/hotspot/share/utilities/intpow.hpp b/src/hotspot/share/utilities/intpow.hpp new file mode 100644 index 0000000000000..0b441a55c4c96 --- /dev/null +++ b/src/hotspot/share/utilities/intpow.hpp @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024, 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. + * + */ + +#ifndef SHARE_UTILITIES_INTPOW_HPP +#define SHARE_UTILITIES_INTPOW_HPP + +#include "metaprogramming/enableIf.hpp" +#include +#include + +// Raise v to the power p mod 2**N, where N is the width of the type T. +template ::value && std::is_unsigned::value)> +static constexpr T intpow(T v, unsigned p) { + if (p == 0) { + return 1; + } + + // We use exponentiation by squaring to calculate the required power. + T a = intpow(v, p / 2); + T b = (p % 2) ? v : 1; + + return a * a * b; +} + +#endif // SHARE_UTILITIES_INTPOW_HPP diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index 7e9d557d11cb7..64f3e787356e0 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -77,11 +77,29 @@ class FloatRegister(Register): def __str__(self): return self.astr("v") + def generate(self): + self.number = random.randint(0, 31) + return self + def nextReg(self): next = FloatRegister() next.number = (self.number + 1) % 32 return next +class LowFloatRegister(Register): + + def __str__(self): + return self.astr("v") + + def generate(self): + self.number = random.randint(0, 15) + return self + + def nextReg(self): + next = FloatRegister() + next.number = (self.number + 1) % 16 + return next + class GeneralRegister(Register): def __str__(self): @@ -1271,6 +1289,75 @@ def astr(self): def aname(self): return self._name +class VectorScalarNEONInstruction(Instruction): + def __init__(self, args): + self._name, self.insname, self.arrangement = args + + def generate(self): + vectorLength = {"8B" : 8, "16B" : 16, "4H" : 4, "8H" : 8, "2S" : 2, "4S" : 4, "1D" : 1, "2D" : 2} [self.arrangement] + self.elemIndex = random.randrange(0, vectorLength) + self.elemSizeSpecifier = self.arrangement[len(self.arrangement) - 1:] + self._firstSIMDreg = LowFloatRegister().generate() + self.numRegs = 3 + return self + + def cstr(self): + buf = Instruction.cstr(self) + str(self._firstSIMDreg) + buf = '%s, __ T%s' % (buf, self.arrangement) + current = self._firstSIMDreg + for cnt in range(1, self.numRegs - 1): + buf = '%s, %s' % (buf, current.nextReg()) + current = current.nextReg() + buf = '%s, %s, %d' % (buf, current.nextReg(), self.elemIndex) + return '%s);' % (buf) + + def astr(self): + buf = '%s\t%s.%s' % (self.insname, self._firstSIMDreg, self.arrangement) + current = self._firstSIMDreg + for cnt in range(1, self.numRegs - 1): + buf = '%s, %s.%s' % (buf, current.nextReg(), self.arrangement) + current = current.nextReg() + buf = '%s, %s.%s[%d]' % (buf, current.nextReg(), self.elemSizeSpecifier, self.elemIndex) + return buf + + def aname(self): + return self._name + +class WideningNEONInstruction(Instruction): + def __init__(self, args): + self._name, self.insname, self.widerArrangement, self.narrowerArrangement = args + + def generate(self): + self._firstSIMDreg = FloatRegister().generate() + return self + + def cstr(self): + buf = Instruction.cstr(self) + str(self._firstSIMDreg) + current = self._firstSIMDreg + for cnt in range(1, self.numWiderRegs): + buf = '%s, %s' % (buf, current.nextReg()) + current = current.nextReg() + buf = '%s, __ T%s' % (buf, self.widerArrangement) + for cnt in range(0, self.numNarrowerRegs): + buf = '%s, %s' % (buf, current.nextReg()) + current = current.nextReg() + buf = '%s, __ T%s' % (buf, self.narrowerArrangement) + return '%s);' % (buf) + + def astr(self): + buf = '%s\t%s.%s' % (self.insname, self._firstSIMDreg, self.widerArrangement) + current = self._firstSIMDreg + for cnt in range(1, self.numWiderRegs): + buf = '%s, %s.%s' % (buf, current.nextReg(), self.widerArrangement) + current = current.nextReg() + for cnt in range(0, self.numNarrowerRegs): + buf = '%s, %s.%s' % (buf, current.nextReg(), self.narrowerArrangement) + current = current.nextReg() + return buf + + def aname(self): + return self._name + class SHA512SIMDOp(Instruction): def generate(self): @@ -1390,6 +1477,10 @@ class TwoRegNEONOp(CommonNEONInstruction): class ThreeRegNEONOp(TwoRegNEONOp): numRegs = 3 +class AddWideNEONOp(WideningNEONInstruction): + numWiderRegs = 2 + numNarrowerRegs = 1 + class NEONFloatCompareWithZero(TwoRegNEONOp): def __init__(self, args): self._name = 'fcm' @@ -1748,6 +1839,17 @@ def generate(kind, names): ["facgt", "facgt", "2D"], ]) +generate(VectorScalarNEONInstruction, + [["fmlavs", "fmla", "2S"], ["mulvs", "mul", "4S"], + ["fmlavs", "fmla", "2D"], + ["fmlsvs", "fmls", "2S"], ["mulvs", "mul", "4S"], + ["fmlsvs", "fmls", "2D"], + ["fmulxvs", "fmulx", "2S"], ["mulvs", "mul", "4S"], + ["fmulxvs", "fmulx", "2D"], + ["mulvs", "mul", "4H"], ["mulvs", "mul", "8H"], + ["mulvs", "mul", "2S"], ["mulvs", "mul", "4S"], + ]) + neonVectorCompareInstructionPrefix = ['cm', 'fcm'] neonIntegerVectorCompareConditions = ['GT', 'GE', 'EQ', 'HI', 'HS'] neonFloatVectorCompareConditions = ['EQ', 'GT', 'GE'] @@ -2081,6 +2183,15 @@ def generate(kind, names): generate(SVEReductionOp, [["andv", 0], ["orv", 0], ["eorv", 0], ["smaxv", 0], ["sminv", 0], ["fminv", 2], ["fmaxv", 2], ["fadda", 2], ["uaddv", 0]]) +generate(AddWideNEONOp, + [["saddwv", "saddw", "8H", "8B"], ["saddwv2", "saddw2", "8H", "16B"], + ["saddwv", "saddw", "4S", "4H"], ["saddwv2", "saddw2", "4S", "8H"], + ["saddwv", "saddw", "2D", "2S"], ["saddwv2", "saddw2", "2D", "4S"], + ["uaddwv", "uaddw", "8H", "8B"], ["uaddwv2", "uaddw2", "8H", "16B"], + ["uaddwv", "uaddw", "4S", "4H"], ["uaddwv2", "uaddw2", "4S", "8H"], + ["uaddwv", "uaddw", "2D", "2S"], ["uaddwv2", "uaddw2", "2D", "4S"], + ]) + print "\n __ bind(forth);" outfile.write("forth:\n") diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index b8260aaf932d1..9805a05c5c150 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -293,9 +293,9 @@ __ ldrshw(r5, Address(r3, 12)); // ldrsh w5, [x3, 12] __ ldrsw(r27, Address(r24, 17)); // ldrsw x27, [x24, 17] __ ldrd(v13, Address(r29, -35)); // ldr d13, [x29, -35] - __ ldrs(v22, Address(r9, -47)); // ldr s22, [x9, -47] + __ ldrs(v23, Address(r9, -47)); // ldr s23, [x9, -47] __ strd(v11, Address(r0, 9)); // str d11, [x0, 9] - __ strs(v20, Address(r0, -127)); // str s20, [x0, -127] + __ strs(v21, Address(r0, -127)); // str s21, [x0, -127] // pre // LoadStoreOp @@ -314,7 +314,7 @@ __ ldrd(v0, Address(__ pre(r14, -54))); // ldr d0, [x14, -54]! __ ldrs(v3, Address(__ pre(r1, 40))); // ldr s3, [x1, 40]! __ strd(v4, Address(__ pre(r14, -94))); // str d4, [x14, -94]! - __ strs(v17, Address(__ pre(r28, -54))); // str s17, [x28, -54]! + __ strs(v18, Address(__ pre(r28, -54))); // str s18, [x28, -54]! // post // LoadStoreOp @@ -331,8 +331,8 @@ __ ldrshw(r3, Address(__ post(r11, -48))); // ldrsh w3, [x11], -48 __ ldrsw(r25, Address(__ post(r23, 22))); // ldrsw x25, [x23], 22 __ ldrd(v0, Address(__ post(r10, -215))); // ldr d0, [x10], -215 - __ ldrs(v17, Address(__ post(r6, 55))); // ldr s17, [x6], 55 - __ strd(v13, Address(__ post(r21, -234))); // str d13, [x21], -234 + __ ldrs(v19, Address(__ post(r6, 55))); // ldr s19, [x6], 55 + __ strd(v14, Address(__ post(r21, -234))); // str d14, [x21], -234 __ strs(v0, Address(__ post(r22, -70))); // str s0, [x22], -70 // base_plus_reg @@ -349,9 +349,9 @@ __ ldrsh(r21, Address(r30, r30, Address::sxtw(1))); // ldrsh x21, [x30, w30, sxtw #1] __ ldrshw(r11, Address(r10, r28, Address::sxtw(1))); // ldrsh w11, [x10, w28, sxtw #1] __ ldrsw(r28, Address(r19, r10, Address::uxtw(0))); // ldrsw x28, [x19, w10, uxtw #0] - __ ldrd(v29, Address(r29, r14, Address::sxtw(0))); // ldr d29, [x29, w14, sxtw #0] + __ ldrd(v30, Address(r29, r14, Address::sxtw(0))); // ldr d30, [x29, w14, sxtw #0] __ ldrs(v8, Address(r5, r5, Address::sxtw(2))); // ldr s8, [x5, w5, sxtw #2] - __ strd(v24, Address(r8, r13, Address::sxtx(0))); // str d24, [x8, x13, sxtx #0] + __ strd(v25, Address(r8, r13, Address::sxtx(0))); // str d25, [x8, x13, sxtx #0] __ strs(v17, Address(r24, r26, Address::lsl(2))); // str s17, [x24, x26, lsl #2] // base_plus_scaled_offset @@ -370,7 +370,7 @@ __ ldrsw(r10, Address(r7, 6372)); // ldrsw x10, [x7, 6372] __ ldrd(v3, Address(r25, 12392)); // ldr d3, [x25, 12392] __ ldrs(v12, Address(r9, 7840)); // ldr s12, [x9, 7840] - __ strd(v23, Address(r1, 12728)); // str d23, [x1, 12728] + __ strd(v24, Address(r1, 12728)); // str d24, [x1, 12728] __ strs(v3, Address(r20, 6924)); // str s3, [x20, 6924] // pcrel @@ -484,63 +484,63 @@ __ umsubl(r13, r10, r7, r5); // umsubl x13, w10, w7, x5 // ThreeRegFloatOp - __ fabds(v29, v15, v3); // fabd s29, s15, s3 - __ fmuls(v11, v12, v15); // fmul s11, s12, s15 - __ fdivs(v30, v30, v17); // fdiv s30, s30, s17 - __ fadds(v19, v20, v15); // fadd s19, s20, s15 - __ fsubs(v15, v9, v21); // fsub s15, s9, s21 - __ fabdd(v2, v9, v27); // fabd d2, d9, d27 - __ fmuld(v7, v29, v30); // fmul d7, d29, d30 - __ fdivd(v17, v1, v2); // fdiv d17, d1, d2 + __ fabds(v30, v15, v3); // fabd s30, s15, s3 + __ fmuls(v12, v12, v16); // fmul s12, s12, s16 + __ fdivs(v31, v31, v18); // fdiv s31, s31, s18 + __ fadds(v19, v21, v16); // fadd s19, s21, s16 + __ fsubs(v15, v10, v21); // fsub s15, s10, s21 + __ fabdd(v2, v10, v28); // fabd d2, d10, d28 + __ fmuld(v7, v30, v31); // fmul d7, d30, d31 + __ fdivd(v18, v1, v2); // fdiv d18, d1, d2 __ faddd(v6, v10, v3); // fadd d6, d10, d3 - __ fsubd(v24, v11, v7); // fsub d24, d11, d7 + __ fsubd(v25, v11, v7); // fsub d25, d11, d7 // FourRegFloatOp - __ fmadds(v1, v11, v0, v3); // fmadd s1, s11, s0, s3 - __ fmsubs(v17, v28, v6, v22); // fmsub s17, s28, s6, s22 - __ fnmadds(v6, v0, v27, v26); // fnmadd s6, s0, s27, s26 - __ fnmadds(v2, v5, v7, v28); // fnmadd s2, s5, s7, s28 - __ fmaddd(v11, v25, v13, v11); // fmadd d11, d25, d13, d11 - __ fmsubd(v23, v19, v8, v17); // fmsub d23, d19, d8, d17 - __ fnmaddd(v21, v25, v20, v19); // fnmadd d21, d25, d20, d19 - __ fnmaddd(v17, v2, v29, v22); // fnmadd d17, d2, d29, d22 + __ fmadds(v1, v12, v0, v3); // fmadd s1, s12, s0, s3 + __ fmsubs(v19, v29, v6, v23); // fmsub s19, s29, s6, s23 + __ fnmadds(v6, v0, v28, v27); // fnmadd s6, s0, s28, s27 + __ fnmadds(v2, v5, v7, v29); // fnmadd s2, s5, s7, s29 + __ fmaddd(v12, v25, v13, v12); // fmadd d12, d25, d13, d12 + __ fmsubd(v24, v19, v8, v18); // fmsub d24, d19, d8, d18 + __ fnmaddd(v22, v26, v21, v20); // fnmadd d22, d26, d21, d20 + __ fnmaddd(v19, v2, v30, v22); // fnmadd d19, d2, d30, d22 // TwoRegFloatOp - __ fmovs(v8, v21); // fmov s8, s21 - __ fabss(v19, v20); // fabs s19, s20 - __ fnegs(v11, v17); // fneg s11, s17 - __ fsqrts(v20, v6); // fsqrt s20, s6 - __ fcvts(v15, v3); // fcvt d15, s3 - __ fcvtsh(v3, v28); // fcvt h3, s28 - __ fcvths(v3, v27); // fcvt s3, h27 - __ fmovd(v14, v14); // fmov d14, d14 - __ fabsd(v10, v12); // fabs d10, d12 - __ fnegd(v11, v17); // fneg d11, d17 - __ fsqrtd(v10, v25); // fsqrt d10, d25 + __ fmovs(v8, v22); // fmov s8, s22 + __ fabss(v19, v21); // fabs s19, s21 + __ fnegs(v12, v18); // fneg s12, s18 + __ fsqrts(v21, v6); // fsqrt s21, s6 + __ fcvts(v16, v3); // fcvt d16, s3 + __ fcvtsh(v3, v29); // fcvt h3, s29 + __ fcvths(v3, v28); // fcvt s3, h28 + __ fmovd(v15, v14); // fmov d15, d14 + __ fabsd(v10, v13); // fabs d10, d13 + __ fnegd(v12, v18); // fneg d12, d18 + __ fsqrtd(v10, v26); // fsqrt d10, d26 __ fcvtd(v7, v7); // fcvt s7, d7 // FloatConvertOp - __ fcvtzsw(r14, v28); // fcvtzs w14, s28 - __ fcvtzs(r0, v22); // fcvtzs x0, s22 + __ fcvtzsw(r14, v29); // fcvtzs w14, s29 + __ fcvtzs(r0, v23); // fcvtzs x0, s23 __ fcvtzdw(r0, v12); // fcvtzs w0, d12 - __ fcvtzd(r23, v13); // fcvtzs x23, d13 + __ fcvtzd(r23, v14); // fcvtzs x23, d14 __ scvtfws(v13, r7); // scvtf s13, w7 - __ scvtfs(v14, r7); // scvtf s14, x7 - __ scvtfwd(v8, r20); // scvtf d8, w20 - __ scvtfd(v17, r28); // scvtf d17, x28 + __ scvtfs(v15, r7); // scvtf s15, x7 + __ scvtfwd(v9, r20); // scvtf d9, w20 + __ scvtfd(v19, r28); // scvtf d19, x28 __ fcvtassw(r30, v16); // fcvtas w30, s16 __ fcvtasd(r2, v9); // fcvtas x2, d9 - __ fcvtmssw(r16, v20); // fcvtms w16, s20 + __ fcvtmssw(r16, v21); // fcvtms w16, s21 __ fcvtmsd(r29, v4); // fcvtms x29, d4 - __ fmovs(r1, v26); // fmov w1, s26 - __ fmovd(r24, v23); // fmov x24, d23 + __ fmovs(r1, v27); // fmov w1, s27 + __ fmovd(r24, v24); // fmov x24, d24 __ fmovs(v14, r21); // fmov s14, w21 - __ fmovd(v12, r5); // fmov d12, x5 + __ fmovd(v13, r5); // fmov d13, x5 // TwoRegFloatOp - __ fcmps(v12, v24); // fcmp s12, s24 - __ fcmpd(v24, v29); // fcmp d24, d29 - __ fcmps(v27, 0.0); // fcmp s27, #0.0 + __ fcmps(v12, v25); // fcmp s12, s25 + __ fcmpd(v25, v30); // fcmp d25, d30 + __ fcmps(v28, 0.0); // fcmp s28, #0.0 __ fcmpd(v21, 0.0); // fcmp d21, #0.0 // LoadStorePairOp @@ -573,250 +573,265 @@ // LdStNEONOp __ ld1(v0, __ T8B, Address(r11)); // ld1 {v0.8B}, [x11] __ ld1(v16, v17, __ T16B, Address(__ post(r26, 32))); // ld1 {v16.16B, v17.16B}, [x26], 32 - __ ld1(v21, v22, v23, __ T1D, Address(__ post(r26, r17))); // ld1 {v21.1D, v22.1D, v23.1D}, [x26], x17 - __ ld1(v26, v27, v28, v29, __ T8H, Address(__ post(r29, 64))); // ld1 {v26.8H, v27.8H, v28.8H, v29.8H}, [x29], 64 - __ ld1r(v21, __ T8B, Address(r6)); // ld1r {v21.8B}, [x6] - __ ld1r(v13, __ T4S, Address(__ post(r29, 4))); // ld1r {v13.4S}, [x29], 4 - __ ld1r(v21, __ T1D, Address(__ post(r12, r16))); // ld1r {v21.1D}, [x12], x16 + __ ld1(v22, v23, v24, __ T1D, Address(__ post(r26, r17))); // ld1 {v22.1D, v23.1D, v24.1D}, [x26], x17 + __ ld1(v27, v28, v29, v30, __ T8H, Address(__ post(r29, 64))); // ld1 {v27.8H, v28.8H, v29.8H, v30.8H}, [x29], 64 + __ ld1r(v22, __ T8B, Address(r6)); // ld1r {v22.8B}, [x6] + __ ld1r(v14, __ T4S, Address(__ post(r29, 4))); // ld1r {v14.4S}, [x29], 4 + __ ld1r(v22, __ T1D, Address(__ post(r12, r16))); // ld1r {v22.1D}, [x12], x16 __ ld2(v1, v2, __ T2D, Address(r0)); // ld2 {v1.2D, v2.2D}, [x0] - __ ld2(v9, v10, __ T4H, Address(__ post(r21, 16))); // ld2 {v9.4H, v10.4H}, [x21], 16 + __ ld2(v10, v11, __ T4H, Address(__ post(r21, 16))); // ld2 {v10.4H, v11.4H}, [x21], 16 __ ld2r(v7, v8, __ T16B, Address(r25)); // ld2r {v7.16B, v8.16B}, [x25] - __ ld2r(v8, v9, __ T2S, Address(__ post(r9, 8))); // ld2r {v8.2S, v9.2S}, [x9], 8 + __ ld2r(v9, v10, __ T2S, Address(__ post(r9, 8))); // ld2r {v9.2S, v10.2S}, [x9], 8 __ ld2r(v9, v10, __ T2D, Address(__ post(r12, r14))); // ld2r {v9.2D, v10.2D}, [x12], x14 __ ld3(v7, v8, v9, __ T4S, Address(__ post(r4, r17))); // ld3 {v7.4S, v8.4S, v9.4S}, [x4], x17 __ ld3(v23, v24, v25, __ T2S, Address(r17)); // ld3 {v23.2S, v24.2S, v25.2S}, [x17] - __ ld3r(v3, v4, v5, __ T8H, Address(r22)); // ld3r {v3.8H, v4.8H, v5.8H}, [x22] - __ ld3r(v12, v13, v14, __ T4S, Address(__ post(r2, 12))); // ld3r {v12.4S, v13.4S, v14.4S}, [x2], 12 - __ ld3r(v15, v16, v17, __ T1D, Address(__ post(r10, r12))); // ld3r {v15.1D, v16.1D, v17.1D}, [x10], x12 + __ ld3r(v4, v5, v6, __ T8H, Address(r22)); // ld3r {v4.8H, v5.8H, v6.8H}, [x22] + __ ld3r(v13, v14, v15, __ T4S, Address(__ post(r2, 12))); // ld3r {v13.4S, v14.4S, v15.4S}, [x2], 12 + __ ld3r(v16, v17, v18, __ T1D, Address(__ post(r10, r12))); // ld3r {v16.1D, v17.1D, v18.1D}, [x10], x12 __ ld4(v4, v5, v6, v7, __ T8H, Address(__ post(r2, 64))); // ld4 {v4.8H, v5.8H, v6.8H, v7.8H}, [x2], 64 __ ld4(v6, v7, v8, v9, __ T8B, Address(__ post(r20, r11))); // ld4 {v6.8B, v7.8B, v8.8B, v9.8B}, [x20], x11 - __ ld4r(v11, v12, v13, v14, __ T8B, Address(r12)); // ld4r {v11.8B, v12.8B, v13.8B, v14.8B}, [x12] - __ ld4r(v15, v16, v17, v18, __ T4H, Address(__ post(r17, 8))); // ld4r {v15.4H, v16.4H, v17.4H, v18.4H}, [x17], 8 + __ ld4r(v12, v13, v14, v15, __ T8B, Address(r12)); // ld4r {v12.8B, v13.8B, v14.8B, v15.8B}, [x12] + __ ld4r(v16, v17, v18, v19, __ T4H, Address(__ post(r17, 8))); // ld4r {v16.4H, v17.4H, v18.4H, v19.4H}, [x17], 8 __ ld4r(v14, v15, v16, v17, __ T2S, Address(__ post(r25, r16))); // ld4r {v14.2S, v15.2S, v16.2S, v17.2S}, [x25], x16 // NEONReduceInstruction __ addv(v20, __ T8B, v21); // addv b20, v21.8B __ addv(v1, __ T16B, v2); // addv b1, v2.16B - __ addv(v22, __ T4H, v23); // addv h22, v23.4H + __ addv(v23, __ T4H, v24); // addv h23, v24.4H __ addv(v30, __ T8H, v31); // addv h30, v31.8H __ addv(v14, __ T4S, v15); // addv s14, v15.4S __ smaxv(v2, __ T8B, v3); // smaxv b2, v3.8B __ smaxv(v6, __ T16B, v7); // smaxv b6, v7.16B __ smaxv(v3, __ T4H, v4); // smaxv h3, v4.4H - __ smaxv(v7, __ T8H, v8); // smaxv h7, v8.8H - __ smaxv(v24, __ T4S, v25); // smaxv s24, v25.4S + __ smaxv(v8, __ T8H, v9); // smaxv h8, v9.8H + __ smaxv(v25, __ T4S, v26); // smaxv s25, v26.4S __ fmaxv(v0, __ T4S, v1); // fmaxv s0, v1.4S __ sminv(v27, __ T8B, v28); // sminv b27, v28.8B - __ uminv(v29, __ T8B, v30); // uminv b29, v30.8B + __ uminv(v30, __ T8B, v31); // uminv b30, v31.8B __ sminv(v5, __ T16B, v6); // sminv b5, v6.16B __ uminv(v5, __ T16B, v6); // uminv b5, v6.16B - __ sminv(v29, __ T4H, v30); // sminv h29, v30.4H + __ sminv(v30, __ T4H, v31); // sminv h30, v31.4H __ uminv(v11, __ T4H, v12); // uminv h11, v12.4H __ sminv(v25, __ T8H, v26); // sminv h25, v26.8H __ uminv(v0, __ T8H, v1); // uminv h0, v1.8H - __ sminv(v30, __ T4S, v31); // sminv s30, v31.4S + __ sminv(v31, __ T4S, v0); // sminv s31, v0.4S __ uminv(v0, __ T4S, v1); // uminv s0, v1.4S - __ fminv(v17, __ T4S, v18); // fminv s17, v18.4S - __ fmaxp(v28, v29, __ S); // fmaxp s28, v29.2S - __ fmaxp(v25, v26, __ D); // fmaxp d25, v26.2D + __ fminv(v19, __ T4S, v20); // fminv s19, v20.4S + __ fmaxp(v29, v30, __ S); // fmaxp s29, v30.2S + __ fmaxp(v26, v27, __ D); // fmaxp d26, v27.2D __ fminp(v9, v10, __ S); // fminp s9, v10.2S - __ fminp(v25, v26, __ D); // fminp d25, v26.2D + __ fminp(v26, v27, __ D); // fminp d26, v27.2D // NEONFloatCompareWithZero __ fcm(Assembler::GT, v12, __ T2S, v13); // fcmgt v12.2S, v13.2S, #0.0 __ fcm(Assembler::GT, v15, __ T4S, v16); // fcmgt v15.4S, v16.4S, #0.0 __ fcm(Assembler::GT, v11, __ T2D, v12); // fcmgt v11.2D, v12.2D, #0.0 - __ fcm(Assembler::GE, v10, __ T2S, v11); // fcmge v10.2S, v11.2S, #0.0 - __ fcm(Assembler::GE, v17, __ T4S, v18); // fcmge v17.4S, v18.4S, #0.0 - __ fcm(Assembler::GE, v24, __ T2D, v25); // fcmge v24.2D, v25.2D, #0.0 - __ fcm(Assembler::EQ, v21, __ T2S, v22); // fcmeq v21.2S, v22.2S, #0.0 - __ fcm(Assembler::EQ, v23, __ T4S, v24); // fcmeq v23.4S, v24.4S, #0.0 + __ fcm(Assembler::GE, v11, __ T2S, v12); // fcmge v11.2S, v12.2S, #0.0 + __ fcm(Assembler::GE, v18, __ T4S, v19); // fcmge v18.4S, v19.4S, #0.0 + __ fcm(Assembler::GE, v25, __ T2D, v26); // fcmge v25.2D, v26.2D, #0.0 + __ fcm(Assembler::EQ, v22, __ T2S, v23); // fcmeq v22.2S, v23.2S, #0.0 + __ fcm(Assembler::EQ, v24, __ T4S, v25); // fcmeq v24.4S, v25.4S, #0.0 __ fcm(Assembler::EQ, v0, __ T2D, v1); // fcmeq v0.2D, v1.2D, #0.0 - __ fcm(Assembler::LT, v16, __ T2S, v17); // fcmlt v16.2S, v17.2S, #0.0 - __ fcm(Assembler::LT, v10, __ T4S, v11); // fcmlt v10.4S, v11.4S, #0.0 + __ fcm(Assembler::LT, v17, __ T2S, v18); // fcmlt v17.2S, v18.2S, #0.0 + __ fcm(Assembler::LT, v11, __ T4S, v12); // fcmlt v11.4S, v12.4S, #0.0 __ fcm(Assembler::LT, v6, __ T2D, v7); // fcmlt v6.2D, v7.2D, #0.0 - __ fcm(Assembler::LE, v28, __ T2S, v29); // fcmle v28.2S, v29.2S, #0.0 + __ fcm(Assembler::LE, v29, __ T2S, v30); // fcmle v29.2S, v30.2S, #0.0 __ fcm(Assembler::LE, v6, __ T4S, v7); // fcmle v6.4S, v7.4S, #0.0 __ fcm(Assembler::LE, v5, __ T2D, v6); // fcmle v5.2D, v6.2D, #0.0 // TwoRegNEONOp __ absr(v5, __ T8B, v6); // abs v5.8B, v6.8B - __ absr(v20, __ T16B, v21); // abs v20.16B, v21.16B - __ absr(v17, __ T4H, v18); // abs v17.4H, v18.4H - __ absr(v15, __ T8H, v16); // abs v15.8H, v16.8H - __ absr(v17, __ T2S, v18); // abs v17.2S, v18.2S - __ absr(v29, __ T4S, v30); // abs v29.4S, v30.4S - __ absr(v26, __ T2D, v27); // abs v26.2D, v27.2D + __ absr(v21, __ T16B, v22); // abs v21.16B, v22.16B + __ absr(v19, __ T4H, v20); // abs v19.4H, v20.4H + __ absr(v16, __ T8H, v17); // abs v16.8H, v17.8H + __ absr(v18, __ T2S, v19); // abs v18.2S, v19.2S + __ absr(v30, __ T4S, v31); // abs v30.4S, v31.4S + __ absr(v27, __ T2D, v28); // abs v27.2D, v28.2D __ fabs(v28, __ T2S, v29); // fabs v28.2S, v29.2S __ fabs(v1, __ T4S, v2); // fabs v1.4S, v2.4S - __ fabs(v27, __ T2D, v28); // fabs v27.2D, v28.2D - __ fneg(v0, __ T2S, v1); // fneg v0.2S, v1.2S + __ fabs(v28, __ T2D, v29); // fabs v28.2D, v29.2D + __ fneg(v1, __ T2S, v2); // fneg v1.2S, v2.2S __ fneg(v20, __ T4S, v21); // fneg v20.4S, v21.4S - __ fneg(v28, __ T2D, v29); // fneg v28.2D, v29.2D - __ fsqrt(v15, __ T2S, v16); // fsqrt v15.2S, v16.2S - __ fsqrt(v12, __ T4S, v13); // fsqrt v12.4S, v13.4S + __ fneg(v29, __ T2D, v30); // fneg v29.2D, v30.2D + __ fsqrt(v16, __ T2S, v17); // fsqrt v16.2S, v17.2S + __ fsqrt(v13, __ T4S, v14); // fsqrt v13.4S, v14.4S __ fsqrt(v10, __ T2D, v11); // fsqrt v10.2D, v11.2D - __ notr(v28, __ T8B, v29); // not v28.8B, v29.8B - __ notr(v28, __ T16B, v29); // not v28.16B, v29.16B + __ notr(v29, __ T8B, v30); // not v29.8B, v30.8B + __ notr(v29, __ T16B, v30); // not v29.16B, v30.16B // ThreeRegNEONOp __ andr(v19, __ T8B, v20, v21); // and v19.8B, v20.8B, v21.8B __ andr(v22, __ T16B, v23, v24); // and v22.16B, v23.16B, v24.16B __ orr(v10, __ T8B, v11, v12); // orr v10.8B, v11.8B, v12.8B __ orr(v4, __ T16B, v5, v6); // orr v4.16B, v5.16B, v6.16B - __ eor(v30, __ T8B, v31, v0); // eor v30.8B, v31.8B, v0.8B - __ eor(v20, __ T16B, v21, v22); // eor v20.16B, v21.16B, v22.16B + __ eor(v31, __ T8B, v0, v1); // eor v31.8B, v0.8B, v1.8B + __ eor(v21, __ T16B, v22, v23); // eor v21.16B, v22.16B, v23.16B __ addv(v8, __ T8B, v9, v10); // add v8.8B, v9.8B, v10.8B - __ addv(v30, __ T16B, v31, v0); // add v30.16B, v31.16B, v0.16B - __ addv(v17, __ T4H, v18, v19); // add v17.4H, v18.4H, v19.4H + __ addv(v31, __ T16B, v0, v1); // add v31.16B, v0.16B, v1.16B + __ addv(v19, __ T4H, v20, v21); // add v19.4H, v20.4H, v21.4H __ addv(v10, __ T8H, v11, v12); // add v10.8H, v11.8H, v12.8H - __ addv(v27, __ T2S, v28, v29); // add v27.2S, v28.2S, v29.2S + __ addv(v28, __ T2S, v29, v30); // add v28.2S, v29.2S, v30.2S __ addv(v2, __ T4S, v3, v4); // add v2.4S, v3.4S, v4.4S - __ addv(v24, __ T2D, v25, v26); // add v24.2D, v25.2D, v26.2D - __ fadd(v4, __ T2S, v5, v6); // fadd v4.2S, v5.2S, v6.2S + __ addv(v25, __ T2D, v26, v27); // add v25.2D, v26.2D, v27.2D + __ fadd(v5, __ T2S, v6, v7); // fadd v5.2S, v6.2S, v7.2S __ fadd(v3, __ T4S, v4, v5); // fadd v3.4S, v4.4S, v5.4S __ fadd(v8, __ T2D, v9, v10); // fadd v8.2D, v9.2D, v10.2D __ subv(v22, __ T8B, v23, v24); // sub v22.8B, v23.8B, v24.8B - __ subv(v17, __ T16B, v18, v19); // sub v17.16B, v18.16B, v19.16B + __ subv(v19, __ T16B, v20, v21); // sub v19.16B, v20.16B, v21.16B __ subv(v13, __ T4H, v14, v15); // sub v13.4H, v14.4H, v15.4H - __ subv(v4, __ T8H, v5, v6); // sub v4.8H, v5.8H, v6.8H - __ subv(v28, __ T2S, v29, v30); // sub v28.2S, v29.2S, v30.2S - __ subv(v23, __ T4S, v24, v25); // sub v23.4S, v24.4S, v25.4S + __ subv(v5, __ T8H, v6, v7); // sub v5.8H, v6.8H, v7.8H + __ subv(v29, __ T2S, v30, v31); // sub v29.2S, v30.2S, v31.2S + __ subv(v24, __ T4S, v25, v26); // sub v24.4S, v25.4S, v26.4S __ subv(v21, __ T2D, v22, v23); // sub v21.2D, v22.2D, v23.2D - __ fsub(v25, __ T2S, v26, v27); // fsub v25.2S, v26.2S, v27.2S + __ fsub(v26, __ T2S, v27, v28); // fsub v26.2S, v27.2S, v28.2S __ fsub(v24, __ T4S, v25, v26); // fsub v24.4S, v25.4S, v26.4S __ fsub(v3, __ T2D, v4, v5); // fsub v3.2D, v4.2D, v5.2D - __ mulv(v23, __ T8B, v24, v25); // mul v23.8B, v24.8B, v25.8B + __ mulv(v24, __ T8B, v25, v26); // mul v24.8B, v25.8B, v26.8B __ mulv(v26, __ T16B, v27, v28); // mul v26.16B, v27.16B, v28.16B __ mulv(v23, __ T4H, v24, v25); // mul v23.4H, v24.4H, v25.4H - __ mulv(v14, __ T8H, v15, v16); // mul v14.8H, v15.8H, v16.8H + __ mulv(v15, __ T8H, v16, v17); // mul v15.8H, v16.8H, v17.8H __ mulv(v21, __ T2S, v22, v23); // mul v21.2S, v22.2S, v23.2S __ mulv(v3, __ T4S, v4, v5); // mul v3.4S, v4.4S, v5.4S - __ fabd(v23, __ T2S, v24, v25); // fabd v23.2S, v24.2S, v25.2S + __ fabd(v24, __ T2S, v25, v26); // fabd v24.2S, v25.2S, v26.2S __ fabd(v8, __ T4S, v9, v10); // fabd v8.4S, v9.4S, v10.4S - __ fabd(v24, __ T2D, v25, v26); // fabd v24.2D, v25.2D, v26.2D - __ faddp(v19, __ T2S, v20, v21); // faddp v19.2S, v20.2S, v21.2S - __ faddp(v15, __ T4S, v16, v17); // faddp v15.4S, v16.4S, v17.4S - __ faddp(v16, __ T2D, v17, v18); // faddp v16.2D, v17.2D, v18.2D + __ fabd(v25, __ T2D, v26, v27); // fabd v25.2D, v26.2D, v27.2D + __ faddp(v20, __ T2S, v21, v22); // faddp v20.2S, v21.2S, v22.2S + __ faddp(v16, __ T4S, v17, v18); // faddp v16.4S, v17.4S, v18.4S + __ faddp(v17, __ T2D, v18, v19); // faddp v17.2D, v18.2D, v19.2D __ fmul(v2, __ T2S, v3, v4); // fmul v2.2S, v3.2S, v4.2S __ fmul(v1, __ T4S, v2, v3); // fmul v1.4S, v2.4S, v3.4S __ fmul(v0, __ T2D, v1, v2); // fmul v0.2D, v1.2D, v2.2D __ mlav(v24, __ T4H, v25, v26); // mla v24.4H, v25.4H, v26.4H __ mlav(v4, __ T8H, v5, v6); // mla v4.8H, v5.8H, v6.8H __ mlav(v3, __ T2S, v4, v5); // mla v3.2S, v4.2S, v5.2S - __ mlav(v11, __ T4S, v12, v13); // mla v11.4S, v12.4S, v13.4S - __ fmla(v30, __ T2S, v31, v0); // fmla v30.2S, v31.2S, v0.2S - __ fmla(v27, __ T4S, v28, v29); // fmla v27.4S, v28.4S, v29.4S - __ fmla(v9, __ T2D, v10, v11); // fmla v9.2D, v10.2D, v11.2D - __ mlsv(v25, __ T4H, v26, v27); // mls v25.4H, v26.4H, v27.4H + __ mlav(v12, __ T4S, v13, v14); // mla v12.4S, v13.4S, v14.4S + __ fmla(v31, __ T2S, v0, v1); // fmla v31.2S, v0.2S, v1.2S + __ fmla(v28, __ T4S, v29, v30); // fmla v28.4S, v29.4S, v30.4S + __ fmla(v10, __ T2D, v11, v12); // fmla v10.2D, v11.2D, v12.2D + __ mlsv(v26, __ T4H, v27, v28); // mls v26.4H, v27.4H, v28.4H __ mlsv(v2, __ T8H, v3, v4); // mls v2.8H, v3.8H, v4.8H __ mlsv(v12, __ T2S, v13, v14); // mls v12.2S, v13.2S, v14.2S - __ mlsv(v17, __ T4S, v18, v19); // mls v17.4S, v18.4S, v19.4S - __ fmls(v30, __ T2S, v31, v0); // fmls v30.2S, v31.2S, v0.2S + __ mlsv(v18, __ T4S, v19, v20); // mls v18.4S, v19.4S, v20.4S + __ fmls(v31, __ T2S, v0, v1); // fmls v31.2S, v0.2S, v1.2S __ fmls(v1, __ T4S, v2, v3); // fmls v1.4S, v2.4S, v3.4S - __ fmls(v12, __ T2D, v13, v14); // fmls v12.2D, v13.2D, v14.2D - __ fdiv(v28, __ T2S, v29, v30); // fdiv v28.2S, v29.2S, v30.2S + __ fmls(v13, __ T2D, v14, v15); // fmls v13.2D, v14.2D, v15.2D + __ fdiv(v29, __ T2S, v30, v31); // fdiv v29.2S, v30.2S, v31.2S __ fdiv(v0, __ T4S, v1, v2); // fdiv v0.4S, v1.4S, v2.4S - __ fdiv(v17, __ T2D, v18, v19); // fdiv v17.2D, v18.2D, v19.2D + __ fdiv(v19, __ T2D, v20, v21); // fdiv v19.2D, v20.2D, v21.2D __ maxv(v12, __ T8B, v13, v14); // smax v12.8B, v13.8B, v14.8B __ maxv(v17, __ T16B, v18, v19); // smax v17.16B, v18.16B, v19.16B - __ maxv(v21, __ T4H, v22, v23); // smax v21.4H, v22.4H, v23.4H - __ maxv(v12, __ T8H, v13, v14); // smax v12.8H, v13.8H, v14.8H - __ maxv(v27, __ T2S, v28, v29); // smax v27.2S, v28.2S, v29.2S - __ maxv(v29, __ T4S, v30, v31); // smax v29.4S, v30.4S, v31.4S - __ smaxp(v30, __ T8B, v31, v0); // smaxp v30.8B, v31.8B, v0.8B + __ maxv(v22, __ T4H, v23, v24); // smax v22.4H, v23.4H, v24.4H + __ maxv(v13, __ T8H, v14, v15); // smax v13.8H, v14.8H, v15.8H + __ maxv(v28, __ T2S, v29, v30); // smax v28.2S, v29.2S, v30.2S + __ maxv(v30, __ T4S, v31, v0); // smax v30.4S, v31.4S, v0.4S + __ smaxp(v31, __ T8B, v0, v1); // smaxp v31.8B, v0.8B, v1.8B __ smaxp(v1, __ T16B, v2, v3); // smaxp v1.16B, v2.16B, v3.16B - __ smaxp(v25, __ T4H, v26, v27); // smaxp v25.4H, v26.4H, v27.4H - __ smaxp(v27, __ T8H, v28, v29); // smaxp v27.8H, v28.8H, v29.8H + __ smaxp(v26, __ T4H, v27, v28); // smaxp v26.4H, v27.4H, v28.4H + __ smaxp(v28, __ T8H, v29, v30); // smaxp v28.8H, v29.8H, v30.8H __ smaxp(v4, __ T2S, v5, v6); // smaxp v4.2S, v5.2S, v6.2S - __ smaxp(v29, __ T4S, v30, v31); // smaxp v29.4S, v30.4S, v31.4S - __ fmax(v3, __ T2S, v4, v5); // fmax v3.2S, v4.2S, v5.2S + __ smaxp(v30, __ T4S, v31, v0); // smaxp v30.4S, v31.4S, v0.4S + __ fmax(v4, __ T2S, v5, v6); // fmax v4.2S, v5.2S, v6.2S __ fmax(v6, __ T4S, v7, v8); // fmax v6.4S, v7.4S, v8.4S - __ fmax(v29, __ T2D, v30, v31); // fmax v29.2D, v30.2D, v31.2D - __ minv(v25, __ T8B, v26, v27); // smin v25.8B, v26.8B, v27.8B - __ minv(v17, __ T16B, v18, v19); // smin v17.16B, v18.16B, v19.16B - __ minv(v8, __ T4H, v9, v10); // smin v8.4H, v9.4H, v10.4H - __ minv(v7, __ T8H, v8, v9); // smin v7.8H, v8.8H, v9.8H + __ fmax(v30, __ T2D, v31, v0); // fmax v30.2D, v31.2D, v0.2D + __ minv(v26, __ T8B, v27, v28); // smin v26.8B, v27.8B, v28.8B + __ minv(v18, __ T16B, v19, v20); // smin v18.16B, v19.16B, v20.16B + __ minv(v9, __ T4H, v10, v11); // smin v9.4H, v10.4H, v11.4H + __ minv(v8, __ T8H, v9, v10); // smin v8.8H, v9.8H, v10.8H __ minv(v12, __ T2S, v13, v14); // smin v12.2S, v13.2S, v14.2S __ minv(v0, __ T4S, v1, v2); // smin v0.4S, v1.4S, v2.4S - __ sminp(v19, __ T8B, v20, v21); // sminp v19.8B, v20.8B, v21.8B + __ sminp(v20, __ T8B, v21, v22); // sminp v20.8B, v21.8B, v22.8B __ sminp(v1, __ T16B, v2, v3); // sminp v1.16B, v2.16B, v3.16B - __ sminp(v23, __ T4H, v24, v25); // sminp v23.4H, v24.4H, v25.4H + __ sminp(v24, __ T4H, v25, v26); // sminp v24.4H, v25.4H, v26.4H __ sminp(v2, __ T8H, v3, v4); // sminp v2.8H, v3.8H, v4.8H __ sminp(v0, __ T2S, v1, v2); // sminp v0.2S, v1.2S, v2.2S - __ sminp(v8, __ T4S, v9, v10); // sminp v8.4S, v9.4S, v10.4S - __ fmin(v23, __ T2S, v24, v25); // fmin v23.2S, v24.2S, v25.2S - __ fmin(v25, __ T4S, v26, v27); // fmin v25.4S, v26.4S, v27.4S - __ fmin(v15, __ T2D, v16, v17); // fmin v15.2D, v16.2D, v17.2D - __ facgt(v29, __ T2S, v30, v31); // facgt v29.2S, v30.2S, v31.2S + __ sminp(v9, __ T4S, v10, v11); // sminp v9.4S, v10.4S, v11.4S + __ fmin(v24, __ T2S, v25, v26); // fmin v24.2S, v25.2S, v26.2S + __ fmin(v26, __ T4S, v27, v28); // fmin v26.4S, v27.4S, v28.4S + __ fmin(v16, __ T2D, v17, v18); // fmin v16.2D, v17.2D, v18.2D + __ facgt(v30, __ T2S, v31, v0); // facgt v30.2S, v31.2S, v0.2S __ facgt(v3, __ T4S, v4, v5); // facgt v3.4S, v4.4S, v5.4S __ facgt(v10, __ T2D, v11, v12); // facgt v10.2D, v11.2D, v12.2D +// VectorScalarNEONInstruction + __ fmlavs(v5, __ T2S, v6, v7, 1); // fmla v5.2S, v6.2S, v7.S[1] + __ mulvs(v9, __ T4S, v10, v11, 0); // mul v9.4S, v10.4S, v11.S[0] + __ fmlavs(v5, __ T2D, v6, v7, 0); // fmla v5.2D, v6.2D, v7.D[0] + __ fmlsvs(v5, __ T2S, v6, v7, 0); // fmls v5.2S, v6.2S, v7.S[0] + __ mulvs(v8, __ T4S, v9, v10, 1); // mul v8.4S, v9.4S, v10.S[1] + __ fmlsvs(v5, __ T2D, v6, v7, 0); // fmls v5.2D, v6.2D, v7.D[0] + __ fmulxvs(v6, __ T2S, v7, v8, 0); // fmulx v6.2S, v7.2S, v8.S[0] + __ mulvs(v6, __ T4S, v7, v8, 1); // mul v6.4S, v7.4S, v8.S[1] + __ fmulxvs(v3, __ T2D, v4, v5, 0); // fmulx v3.2D, v4.2D, v5.D[0] + __ mulvs(v13, __ T4H, v14, v15, 2); // mul v13.4H, v14.4H, v15.H[2] + __ mulvs(v2, __ T8H, v3, v4, 4); // mul v2.8H, v3.8H, v4.H[4] + __ mulvs(v2, __ T2S, v3, v4, 0); // mul v2.2S, v3.2S, v4.S[0] + __ mulvs(v9, __ T4S, v10, v11, 1); // mul v9.4S, v10.4S, v11.S[1] + // NEONVectorCompare - __ cm(Assembler::GT, v22, __ T8B, v23, v24); // cmgt v22.8B, v23.8B, v24.8B - __ cm(Assembler::GT, v10, __ T16B, v11, v12); // cmgt v10.16B, v11.16B, v12.16B - __ cm(Assembler::GT, v4, __ T4H, v5, v6); // cmgt v4.4H, v5.4H, v6.4H - __ cm(Assembler::GT, v17, __ T8H, v18, v19); // cmgt v17.8H, v18.8H, v19.8H - __ cm(Assembler::GT, v1, __ T2S, v2, v3); // cmgt v1.2S, v2.2S, v3.2S - __ cm(Assembler::GT, v11, __ T4S, v12, v13); // cmgt v11.4S, v12.4S, v13.4S - __ cm(Assembler::GT, v7, __ T2D, v8, v9); // cmgt v7.2D, v8.2D, v9.2D - __ cm(Assembler::GE, v10, __ T8B, v11, v12); // cmge v10.8B, v11.8B, v12.8B - __ cm(Assembler::GE, v15, __ T16B, v16, v17); // cmge v15.16B, v16.16B, v17.16B - __ cm(Assembler::GE, v16, __ T4H, v17, v18); // cmge v16.4H, v17.4H, v18.4H - __ cm(Assembler::GE, v2, __ T8H, v3, v4); // cmge v2.8H, v3.8H, v4.8H - __ cm(Assembler::GE, v9, __ T2S, v10, v11); // cmge v9.2S, v10.2S, v11.2S - __ cm(Assembler::GE, v11, __ T4S, v12, v13); // cmge v11.4S, v12.4S, v13.4S - __ cm(Assembler::GE, v12, __ T2D, v13, v14); // cmge v12.2D, v13.2D, v14.2D - __ cm(Assembler::EQ, v14, __ T8B, v15, v16); // cmeq v14.8B, v15.8B, v16.8B - __ cm(Assembler::EQ, v13, __ T16B, v14, v15); // cmeq v13.16B, v14.16B, v15.16B - __ cm(Assembler::EQ, v2, __ T4H, v3, v4); // cmeq v2.4H, v3.4H, v4.4H - __ cm(Assembler::EQ, v6, __ T8H, v7, v8); // cmeq v6.8H, v7.8H, v8.8H - __ cm(Assembler::EQ, v19, __ T2S, v20, v21); // cmeq v19.2S, v20.2S, v21.2S - __ cm(Assembler::EQ, v25, __ T4S, v26, v27); // cmeq v25.4S, v26.4S, v27.4S - __ cm(Assembler::EQ, v15, __ T2D, v16, v17); // cmeq v15.2D, v16.2D, v17.2D - __ cm(Assembler::HI, v4, __ T8B, v5, v6); // cmhi v4.8B, v5.8B, v6.8B - __ cm(Assembler::HI, v2, __ T16B, v3, v4); // cmhi v2.16B, v3.16B, v4.16B - __ cm(Assembler::HI, v4, __ T4H, v5, v6); // cmhi v4.4H, v5.4H, v6.4H - __ cm(Assembler::HI, v11, __ T8H, v12, v13); // cmhi v11.8H, v12.8H, v13.8H - __ cm(Assembler::HI, v17, __ T2S, v18, v19); // cmhi v17.2S, v18.2S, v19.2S - __ cm(Assembler::HI, v20, __ T4S, v21, v22); // cmhi v20.4S, v21.4S, v22.4S - __ cm(Assembler::HI, v16, __ T2D, v17, v18); // cmhi v16.2D, v17.2D, v18.2D - __ cm(Assembler::HS, v17, __ T8B, v18, v19); // cmhs v17.8B, v18.8B, v19.8B - __ cm(Assembler::HS, v10, __ T16B, v11, v12); // cmhs v10.16B, v11.16B, v12.16B - __ cm(Assembler::HS, v20, __ T4H, v21, v22); // cmhs v20.4H, v21.4H, v22.4H - __ cm(Assembler::HS, v22, __ T8H, v23, v24); // cmhs v22.8H, v23.8H, v24.8H - __ cm(Assembler::HS, v12, __ T2S, v13, v14); // cmhs v12.2S, v13.2S, v14.2S - __ cm(Assembler::HS, v25, __ T4S, v26, v27); // cmhs v25.4S, v26.4S, v27.4S - __ cm(Assembler::HS, v23, __ T2D, v24, v25); // cmhs v23.2D, v24.2D, v25.2D - __ fcm(Assembler::EQ, v28, __ T2S, v29, v30); // fcmeq v28.2S, v29.2S, v30.2S - __ fcm(Assembler::EQ, v14, __ T4S, v15, v16); // fcmeq v14.4S, v15.4S, v16.4S - __ fcm(Assembler::EQ, v10, __ T2D, v11, v12); // fcmeq v10.2D, v11.2D, v12.2D - __ fcm(Assembler::GT, v24, __ T2S, v25, v26); // fcmgt v24.2S, v25.2S, v26.2S - __ fcm(Assembler::GT, v1, __ T4S, v2, v3); // fcmgt v1.4S, v2.4S, v3.4S - __ fcm(Assembler::GT, v11, __ T2D, v12, v13); // fcmgt v11.2D, v12.2D, v13.2D - __ fcm(Assembler::GE, v30, __ T2S, v31, v0); // fcmge v30.2S, v31.2S, v0.2S - __ fcm(Assembler::GE, v10, __ T4S, v11, v12); // fcmge v10.4S, v11.4S, v12.4S - __ fcm(Assembler::GE, v15, __ T2D, v16, v17); // fcmge v15.2D, v16.2D, v17.2D + __ cm(Assembler::GT, v21, __ T8B, v22, v23); // cmgt v21.8B, v22.8B, v23.8B + __ cm(Assembler::GT, v16, __ T16B, v17, v18); // cmgt v16.16B, v17.16B, v18.16B + __ cm(Assembler::GT, v18, __ T4H, v19, v20); // cmgt v18.4H, v19.4H, v20.4H + __ cm(Assembler::GT, v11, __ T8H, v12, v13); // cmgt v11.8H, v12.8H, v13.8H + __ cm(Assembler::GT, v21, __ T2S, v22, v23); // cmgt v21.2S, v22.2S, v23.2S + __ cm(Assembler::GT, v23, __ T4S, v24, v25); // cmgt v23.4S, v24.4S, v25.4S + __ cm(Assembler::GT, v12, __ T2D, v13, v14); // cmgt v12.2D, v13.2D, v14.2D + __ cm(Assembler::GE, v26, __ T8B, v27, v28); // cmge v26.8B, v27.8B, v28.8B + __ cm(Assembler::GE, v23, __ T16B, v24, v25); // cmge v23.16B, v24.16B, v25.16B + __ cm(Assembler::GE, v28, __ T4H, v29, v30); // cmge v28.4H, v29.4H, v30.4H + __ cm(Assembler::GE, v14, __ T8H, v15, v16); // cmge v14.8H, v15.8H, v16.8H + __ cm(Assembler::GE, v11, __ T2S, v12, v13); // cmge v11.2S, v12.2S, v13.2S + __ cm(Assembler::GE, v24, __ T4S, v25, v26); // cmge v24.4S, v25.4S, v26.4S + __ cm(Assembler::GE, v1, __ T2D, v2, v3); // cmge v1.2D, v2.2D, v3.2D + __ cm(Assembler::EQ, v12, __ T8B, v13, v14); // cmeq v12.8B, v13.8B, v14.8B + __ cm(Assembler::EQ, v31, __ T16B, v0, v1); // cmeq v31.16B, v0.16B, v1.16B + __ cm(Assembler::EQ, v10, __ T4H, v11, v12); // cmeq v10.4H, v11.4H, v12.4H + __ cm(Assembler::EQ, v16, __ T8H, v17, v18); // cmeq v16.8H, v17.8H, v18.8H + __ cm(Assembler::EQ, v7, __ T2S, v8, v9); // cmeq v7.2S, v8.2S, v9.2S + __ cm(Assembler::EQ, v2, __ T4S, v3, v4); // cmeq v2.4S, v3.4S, v4.4S + __ cm(Assembler::EQ, v3, __ T2D, v4, v5); // cmeq v3.2D, v4.2D, v5.2D + __ cm(Assembler::HI, v13, __ T8B, v14, v15); // cmhi v13.8B, v14.8B, v15.8B + __ cm(Assembler::HI, v19, __ T16B, v20, v21); // cmhi v19.16B, v20.16B, v21.16B + __ cm(Assembler::HI, v17, __ T4H, v18, v19); // cmhi v17.4H, v18.4H, v19.4H + __ cm(Assembler::HI, v16, __ T8H, v17, v18); // cmhi v16.8H, v17.8H, v18.8H + __ cm(Assembler::HI, v3, __ T2S, v4, v5); // cmhi v3.2S, v4.2S, v5.2S + __ cm(Assembler::HI, v1, __ T4S, v2, v3); // cmhi v1.4S, v2.4S, v3.4S + __ cm(Assembler::HI, v11, __ T2D, v12, v13); // cmhi v11.2D, v12.2D, v13.2D + __ cm(Assembler::HS, v30, __ T8B, v31, v0); // cmhs v30.8B, v31.8B, v0.8B + __ cm(Assembler::HS, v5, __ T16B, v6, v7); // cmhs v5.16B, v6.16B, v7.16B + __ cm(Assembler::HS, v8, __ T4H, v9, v10); // cmhs v8.4H, v9.4H, v10.4H + __ cm(Assembler::HS, v15, __ T8H, v16, v17); // cmhs v15.8H, v16.8H, v17.8H + __ cm(Assembler::HS, v29, __ T2S, v30, v31); // cmhs v29.2S, v30.2S, v31.2S + __ cm(Assembler::HS, v30, __ T4S, v31, v0); // cmhs v30.4S, v31.4S, v0.4S + __ cm(Assembler::HS, v0, __ T2D, v1, v2); // cmhs v0.2D, v1.2D, v2.2D + __ fcm(Assembler::EQ, v20, __ T2S, v21, v22); // fcmeq v20.2S, v21.2S, v22.2S + __ fcm(Assembler::EQ, v7, __ T4S, v8, v9); // fcmeq v7.4S, v8.4S, v9.4S + __ fcm(Assembler::EQ, v20, __ T2D, v21, v22); // fcmeq v20.2D, v21.2D, v22.2D + __ fcm(Assembler::GT, v23, __ T2S, v24, v25); // fcmgt v23.2S, v24.2S, v25.2S + __ fcm(Assembler::GT, v28, __ T4S, v29, v30); // fcmgt v28.4S, v29.4S, v30.4S + __ fcm(Assembler::GT, v21, __ T2D, v22, v23); // fcmgt v21.2D, v22.2D, v23.2D + __ fcm(Assembler::GE, v27, __ T2S, v28, v29); // fcmge v27.2S, v28.2S, v29.2S + __ fcm(Assembler::GE, v25, __ T4S, v26, v27); // fcmge v25.4S, v26.4S, v27.4S + __ fcm(Assembler::GE, v5, __ T2D, v6, v7); // fcmge v5.2D, v6.2D, v7.2D // SVEComparisonWithZero - __ sve_fcm(Assembler::EQ, p3, __ S, p3, z2, 0.0); // fcmeq p3.s, p3/z, z2.s, #0.0 - __ sve_fcm(Assembler::GT, p9, __ D, p0, z16, 0.0); // fcmgt p9.d, p0/z, z16.d, #0.0 - __ sve_fcm(Assembler::GE, p0, __ D, p1, z11, 0.0); // fcmge p0.d, p1/z, z11.d, #0.0 - __ sve_fcm(Assembler::LT, p4, __ D, p7, z14, 0.0); // fcmlt p4.d, p7/z, z14.d, #0.0 - __ sve_fcm(Assembler::LE, p0, __ S, p5, z20, 0.0); // fcmle p0.s, p5/z, z20.s, #0.0 - __ sve_fcm(Assembler::NE, p11, __ D, p6, z27, 0.0); // fcmne p11.d, p6/z, z27.d, #0.0 + __ sve_fcm(Assembler::EQ, p0, __ D, p7, z23, 0.0); // fcmeq p0.d, p7/z, z23.d, #0.0 + __ sve_fcm(Assembler::GT, p2, __ S, p7, z12, 0.0); // fcmgt p2.s, p7/z, z12.s, #0.0 + __ sve_fcm(Assembler::GE, p7, __ D, p7, z29, 0.0); // fcmge p7.d, p7/z, z29.d, #0.0 + __ sve_fcm(Assembler::LT, p9, __ S, p3, z31, 0.0); // fcmlt p9.s, p3/z, z31.s, #0.0 + __ sve_fcm(Assembler::LE, p9, __ D, p6, z31, 0.0); // fcmle p9.d, p6/z, z31.d, #0.0 + __ sve_fcm(Assembler::NE, p10, __ S, p2, z16, 0.0); // fcmne p10.s, p2/z, z16.s, #0.0 // SVEComparisonWithImm - __ sve_cmp(Assembler::EQ, p12, __ B, p5, z4, 0); // cmpeq p12.b, p5/z, z4.b, #0 - __ sve_cmp(Assembler::GT, p15, __ H, p2, z5, 12); // cmpgt p15.h, p2/z, z5.h, #12 - __ sve_cmp(Assembler::GE, p7, __ S, p7, z28, 3); // cmpge p7.s, p7/z, z28.s, #3 - __ sve_cmp(Assembler::LT, p15, __ H, p4, z5, 15); // cmplt p15.h, p4/z, z5.h, #15 - __ sve_cmp(Assembler::LE, p9, __ S, p4, z26, -4); // cmple p9.s, p4/z, z26.s, #-4 - __ sve_cmp(Assembler::NE, p5, __ B, p7, z9, 1); // cmpne p5.b, p7/z, z9.b, #1 - __ sve_cmp(Assembler::HS, p13, __ D, p1, z27, 43); // cmphs p13.d, p1/z, z27.d, #43 - __ sve_cmp(Assembler::HI, p10, __ B, p6, z9, 70); // cmphi p10.b, p6/z, z9.b, #70 - __ sve_cmp(Assembler::LS, p8, __ B, p7, z22, 61); // cmpls p8.b, p7/z, z22.b, #61 - __ sve_cmp(Assembler::LO, p11, __ S, p5, z17, 11); // cmplo p11.s, p5/z, z17.s, #11 + __ sve_cmp(Assembler::EQ, p4, __ D, p4, z6, 11); // cmpeq p4.d, p4/z, z6.d, #11 + __ sve_cmp(Assembler::GT, p14, __ B, p2, z30, 4); // cmpgt p14.b, p2/z, z30.b, #4 + __ sve_cmp(Assembler::GE, p5, __ D, p4, z4, 1); // cmpge p5.d, p4/z, z4.d, #1 + __ sve_cmp(Assembler::LT, p11, __ D, p3, z3, 6); // cmplt p11.d, p3/z, z3.d, #6 + __ sve_cmp(Assembler::LE, p9, __ S, p0, z19, -1); // cmple p9.s, p0/z, z19.s, #-1 + __ sve_cmp(Assembler::NE, p3, __ S, p2, z12, -3); // cmpne p3.s, p2/z, z12.s, #-3 + __ sve_cmp(Assembler::HS, p11, __ D, p4, z1, 20); // cmphs p11.d, p4/z, z1.d, #20 + __ sve_cmp(Assembler::HI, p8, __ S, p5, z2, 53); // cmphi p8.s, p5/z, z2.s, #53 + __ sve_cmp(Assembler::LS, p5, __ D, p6, z21, 49); // cmpls p5.d, p6/z, z21.d, #49 + __ sve_cmp(Assembler::LO, p13, __ B, p7, z3, 97); // cmplo p13.b, p7/z, z3.b, #97 // SpecialCases __ ccmn(zr, zr, 3u, Assembler::LE); // ccmn xzr, xzr, #3, LE @@ -1071,215 +1086,229 @@ __ fmovd(v0, -1.0625); // fmov d0, #-1.0625 // LSEOp - __ swp(Assembler::xword, r15, r6, r12); // swp x15, x6, [x12] - __ ldadd(Assembler::xword, r16, r11, r13); // ldadd x16, x11, [x13] - __ ldbic(Assembler::xword, r23, r1, r30); // ldclr x23, x1, [x30] - __ ldeor(Assembler::xword, r19, r5, r17); // ldeor x19, x5, [x17] - __ ldorr(Assembler::xword, r2, r16, r22); // ldset x2, x16, [x22] - __ ldsmin(Assembler::xword, r13, r10, r21); // ldsmin x13, x10, [x21] - __ ldsmax(Assembler::xword, r29, r27, r12); // ldsmax x29, x27, [x12] - __ ldumin(Assembler::xword, r27, r3, r1); // ldumin x27, x3, [x1] - __ ldumax(Assembler::xword, zr, r24, r19); // ldumax xzr, x24, [x19] + __ swp(Assembler::xword, r19, r17, r9); // swp x19, x17, [x9] + __ ldadd(Assembler::xword, r28, r27, r15); // ldadd x28, x27, [x15] + __ ldbic(Assembler::xword, r7, r21, r23); // ldclr x7, x21, [x23] + __ ldeor(Assembler::xword, zr, r25, r2); // ldeor xzr, x25, [x2] + __ ldorr(Assembler::xword, zr, r27, r15); // ldset xzr, x27, [x15] + __ ldsmin(Assembler::xword, r10, r23, r19); // ldsmin x10, x23, [x19] + __ ldsmax(Assembler::xword, r3, r16, r0); // ldsmax x3, x16, [x0] + __ ldumin(Assembler::xword, r25, r26, r23); // ldumin x25, x26, [x23] + __ ldumax(Assembler::xword, r2, r16, r12); // ldumax x2, x16, [x12] // LSEOp - __ swpa(Assembler::xword, r17, r9, r28); // swpa x17, x9, [x28] - __ ldadda(Assembler::xword, r27, r15, r7); // ldadda x27, x15, [x7] - __ ldbica(Assembler::xword, r21, r23, sp); // ldclra x21, x23, [sp] - __ ldeora(Assembler::xword, r25, r2, sp); // ldeora x25, x2, [sp] - __ ldorra(Assembler::xword, r27, r16, r10); // ldseta x27, x16, [x10] - __ ldsmina(Assembler::xword, r23, r19, r3); // ldsmina x23, x19, [x3] - __ ldsmaxa(Assembler::xword, r16, r0, r25); // ldsmaxa x16, x0, [x25] - __ ldumina(Assembler::xword, r26, r23, r2); // ldumina x26, x23, [x2] - __ ldumaxa(Assembler::xword, r16, r12, r4); // ldumaxa x16, x12, [x4] + __ swpa(Assembler::xword, r4, r28, r30); // swpa x4, x28, [x30] + __ ldadda(Assembler::xword, r29, r16, r27); // ldadda x29, x16, [x27] + __ ldbica(Assembler::xword, r6, r9, r29); // ldclra x6, x9, [x29] + __ ldeora(Assembler::xword, r16, r7, r4); // ldeora x16, x7, [x4] + __ ldorra(Assembler::xword, r7, r15, r9); // ldseta x7, x15, [x9] + __ ldsmina(Assembler::xword, r23, r8, r2); // ldsmina x23, x8, [x2] + __ ldsmaxa(Assembler::xword, r28, r21, sp); // ldsmaxa x28, x21, [sp] + __ ldumina(Assembler::xword, r5, r27, r0); // ldumina x5, x27, [x0] + __ ldumaxa(Assembler::xword, r17, r15, r4); // ldumaxa x17, x15, [x4] // LSEOp - __ swpal(Assembler::xword, r28, r30, r29); // swpal x28, x30, [x29] - __ ldaddal(Assembler::xword, r16, r27, r6); // ldaddal x16, x27, [x6] - __ ldbical(Assembler::xword, r9, r29, r15); // ldclral x9, x29, [x15] - __ ldeoral(Assembler::xword, r7, r4, r7); // ldeoral x7, x4, [x7] - __ ldorral(Assembler::xword, r15, r9, r23); // ldsetal x15, x9, [x23] - __ ldsminal(Assembler::xword, r8, r2, r28); // ldsminal x8, x2, [x28] - __ ldsmaxal(Assembler::xword, r21, zr, r5); // ldsmaxal x21, xzr, [x5] - __ lduminal(Assembler::xword, r27, r0, r17); // lduminal x27, x0, [x17] - __ ldumaxal(Assembler::xword, r15, r4, r26); // ldumaxal x15, x4, [x26] + __ swpal(Assembler::xword, r26, r8, r28); // swpal x26, x8, [x28] + __ ldaddal(Assembler::xword, r22, r27, r27); // ldaddal x22, x27, [x27] + __ ldbical(Assembler::xword, r25, r23, r0); // ldclral x25, x23, [x0] + __ ldeoral(Assembler::xword, r4, r6, r15); // ldeoral x4, x6, [x15] + __ ldorral(Assembler::xword, r0, r4, r15); // ldsetal x0, x4, [x15] + __ ldsminal(Assembler::xword, r1, r10, r7); // ldsminal x1, x10, [x7] + __ ldsmaxal(Assembler::xword, r5, r10, r28); // ldsmaxal x5, x10, [x28] + __ lduminal(Assembler::xword, r7, r20, r23); // lduminal x7, x20, [x23] + __ ldumaxal(Assembler::xword, r21, r6, r11); // ldumaxal x21, x6, [x11] // LSEOp - __ swpl(Assembler::xword, r8, r28, r22); // swpl x8, x28, [x22] - __ ldaddl(Assembler::xword, r27, r27, r25); // ldaddl x27, x27, [x25] - __ ldbicl(Assembler::xword, r23, r0, r4); // ldclrl x23, x0, [x4] - __ ldeorl(Assembler::xword, r6, r16, r0); // ldeorl x6, x16, [x0] - __ ldorrl(Assembler::xword, r4, r15, r1); // ldsetl x4, x15, [x1] - __ ldsminl(Assembler::xword, r10, r7, r5); // ldsminl x10, x7, [x5] - __ ldsmaxl(Assembler::xword, r10, r28, r7); // ldsmaxl x10, x28, [x7] - __ lduminl(Assembler::xword, r20, r23, r21); // lduminl x20, x23, [x21] - __ ldumaxl(Assembler::xword, r6, r11, r8); // ldumaxl x6, x11, [x8] + __ swpl(Assembler::xword, r8, r17, sp); // swpl x8, x17, [sp] + __ ldaddl(Assembler::xword, r6, r17, r2); // ldaddl x6, x17, [x2] + __ ldbicl(Assembler::xword, r12, r30, r29); // ldclrl x12, x30, [x29] + __ ldeorl(Assembler::xword, r3, r27, r22); // ldeorl x3, x27, [x22] + __ ldorrl(Assembler::xword, r29, r14, r13); // ldsetl x29, x14, [x13] + __ ldsminl(Assembler::xword, r28, r17, r24); // ldsminl x28, x17, [x24] + __ ldsmaxl(Assembler::xword, r5, r2, r14); // ldsmaxl x5, x2, [x14] + __ lduminl(Assembler::xword, r10, r16, r11); // lduminl x10, x16, [x11] + __ ldumaxl(Assembler::xword, r27, r23, r12); // ldumaxl x27, x23, [x12] // LSEOp - __ swp(Assembler::word, r17, zr, r6); // swp w17, wzr, [x6] - __ ldadd(Assembler::word, r17, r2, r12); // ldadd w17, w2, [x12] - __ ldbic(Assembler::word, r30, r29, r3); // ldclr w30, w29, [x3] - __ ldeor(Assembler::word, r27, r22, r29); // ldeor w27, w22, [x29] - __ ldorr(Assembler::word, r14, r13, r28); // ldset w14, w13, [x28] - __ ldsmin(Assembler::word, r17, r24, r5); // ldsmin w17, w24, [x5] - __ ldsmax(Assembler::word, r2, r14, r10); // ldsmax w2, w14, [x10] - __ ldumin(Assembler::word, r16, r11, r27); // ldumin w16, w11, [x27] - __ ldumax(Assembler::word, r23, r12, r4); // ldumax w23, w12, [x4] + __ swp(Assembler::word, r4, r22, r17); // swp w4, w22, [x17] + __ ldadd(Assembler::word, r4, r1, r19); // ldadd w4, w1, [x19] + __ ldbic(Assembler::word, r16, r16, r13); // ldclr w16, w16, [x13] + __ ldeor(Assembler::word, r14, r12, r2); // ldeor w14, w12, [x2] + __ ldorr(Assembler::word, r17, r3, r21); // ldset w17, w3, [x21] + __ ldsmin(Assembler::word, r23, r5, r6); // ldsmin w23, w5, [x6] + __ ldsmax(Assembler::word, r7, r19, r13); // ldsmax w7, w19, [x13] + __ ldumin(Assembler::word, r28, r17, r16); // ldumin w28, w17, [x16] + __ ldumax(Assembler::word, r6, r2, r29); // ldumax w6, w2, [x29] // LSEOp - __ swpa(Assembler::word, r22, r17, r4); // swpa w22, w17, [x4] - __ ldadda(Assembler::word, r1, r19, r16); // ldadda w1, w19, [x16] - __ ldbica(Assembler::word, r16, r13, r14); // ldclra w16, w13, [x14] - __ ldeora(Assembler::word, r12, r2, r17); // ldeora w12, w2, [x17] - __ ldorra(Assembler::word, r3, r21, r23); // ldseta w3, w21, [x23] - __ ldsmina(Assembler::word, r5, r6, r7); // ldsmina w5, w6, [x7] - __ ldsmaxa(Assembler::word, r19, r13, r28); // ldsmaxa w19, w13, [x28] - __ ldumina(Assembler::word, r17, r16, r6); // ldumina w17, w16, [x6] - __ ldumaxa(Assembler::word, r2, r29, r3); // ldumaxa w2, w29, [x3] + __ swpa(Assembler::word, r3, r4, r6); // swpa w3, w4, [x6] + __ ldadda(Assembler::word, r16, r20, r13); // ldadda w16, w20, [x13] + __ ldbica(Assembler::word, r12, r20, r8); // ldclra w12, w20, [x8] + __ ldeora(Assembler::word, r25, r20, r19); // ldeora w25, w20, [x19] + __ ldorra(Assembler::word, r0, r11, r24); // ldseta w0, w11, [x24] + __ ldsmina(Assembler::word, r6, r20, sp); // ldsmina w6, w20, [sp] + __ ldsmaxa(Assembler::word, r14, r16, r6); // ldsmaxa w14, w16, [x6] + __ ldumina(Assembler::word, r0, r7, r15); // ldumina w0, w7, [x15] + __ ldumaxa(Assembler::word, r19, r26, r9); // ldumaxa w19, w26, [x9] // LSEOp - __ swpal(Assembler::word, r4, r6, r15); // swpal w4, w6, [x15] - __ ldaddal(Assembler::word, r20, r13, r12); // ldaddal w20, w13, [x12] - __ ldbical(Assembler::word, r20, r8, r25); // ldclral w20, w8, [x25] - __ ldeoral(Assembler::word, r20, r19, r0); // ldeoral w20, w19, [x0] - __ ldorral(Assembler::word, r11, r24, r6); // ldsetal w11, w24, [x6] - __ ldsminal(Assembler::word, r20, zr, r14); // ldsminal w20, wzr, [x14] - __ ldsmaxal(Assembler::word, r16, r6, r0); // ldsmaxal w16, w6, [x0] - __ lduminal(Assembler::word, r7, r15, r19); // lduminal w7, w15, [x19] - __ ldumaxal(Assembler::word, r26, r9, r10); // ldumaxal w26, w9, [x10] + __ swpal(Assembler::word, r10, r23, r21); // swpal w10, w23, [x21] + __ ldaddal(Assembler::word, r22, r28, r2); // ldaddal w22, w28, [x2] + __ ldbical(Assembler::word, r3, r15, r19); // ldclral w3, w15, [x19] + __ ldeoral(Assembler::word, r20, r7, r4); // ldeoral w20, w7, [x4] + __ ldorral(Assembler::word, r29, r7, r0); // ldsetal w29, w7, [x0] + __ ldsminal(Assembler::word, r9, r16, r20); // ldsminal w9, w16, [x20] + __ ldsmaxal(Assembler::word, r23, r4, r16); // ldsmaxal w23, w4, [x16] + __ lduminal(Assembler::word, r10, r23, r11); // lduminal w10, w23, [x11] + __ ldumaxal(Assembler::word, r25, r6, sp); // ldumaxal w25, w6, [sp] // LSEOp - __ swpl(Assembler::word, r23, r21, r22); // swpl w23, w21, [x22] - __ ldaddl(Assembler::word, r28, r2, r3); // ldaddl w28, w2, [x3] - __ ldbicl(Assembler::word, r15, r19, r20); // ldclrl w15, w19, [x20] - __ ldeorl(Assembler::word, r7, r4, r29); // ldeorl w7, w4, [x29] - __ ldorrl(Assembler::word, r7, r0, r9); // ldsetl w7, w0, [x9] - __ ldsminl(Assembler::word, r16, r20, r23); // ldsminl w16, w20, [x23] - __ ldsmaxl(Assembler::word, r4, r16, r10); // ldsmaxl w4, w16, [x10] - __ lduminl(Assembler::word, r23, r11, r25); // lduminl w23, w11, [x25] - __ ldumaxl(Assembler::word, r6, zr, r16); // ldumaxl w6, wzr, [x16] + __ swpl(Assembler::word, r16, r13, r23); // swpl w16, w13, [x23] + __ ldaddl(Assembler::word, r12, r1, r14); // ldaddl w12, w1, [x14] + __ ldbicl(Assembler::word, r9, r21, r16); // ldclrl w9, w21, [x16] + __ ldeorl(Assembler::word, r26, r15, r4); // ldeorl w26, w15, [x4] + __ ldorrl(Assembler::word, r4, r16, r8); // ldsetl w4, w16, [x8] + __ ldsminl(Assembler::word, r6, r30, r4); // ldsminl w6, w30, [x4] + __ ldsmaxl(Assembler::word, r29, r17, r29); // ldsmaxl w29, w17, [x29] + __ lduminl(Assembler::word, r26, r9, r15); // lduminl w26, w9, [x15] + __ ldumaxl(Assembler::word, r2, r11, r29); // ldumaxl w2, w11, [x29] // SHA3SIMDOp - __ bcax(v13, __ T16B, v22, v11, v1); // bcax v13.16B, v22.16B, v11.16B, v1.16B - __ eor3(v13, __ T16B, v8, v20, v16); // eor3 v13.16B, v8.16B, v20.16B, v16.16B - __ rax1(v25, __ T2D, v15, v4); // rax1 v25.2D, v15.2D, v4.2D - __ xar(v4, __ T2D, v17, v8, 13); // xar v4.2D, v17.2D, v8.2D, #13 + __ bcax(v3, __ T16B, v7, v1, v27); // bcax v3.16B, v7.16B, v1.16B, v27.16B + __ eor3(v21, __ T16B, v18, v14, v8); // eor3 v21.16B, v18.16B, v14.16B, v8.16B + __ rax1(v18, __ T2D, v22, v25); // rax1 v18.2D, v22.2D, v25.2D + __ xar(v5, __ T2D, v20, v21, 37); // xar v5.2D, v20.2D, v21.2D, #37 // SHA512SIMDOp - __ sha512h(v29, __ T2D, v4, v28); // sha512h q29, q4, v28.2D - __ sha512h2(v16, __ T2D, v29, v26); // sha512h2 q16, q29, v26.2D - __ sha512su0(v9, __ T2D, v14); // sha512su0 v9.2D, v14.2D - __ sha512su1(v2, __ T2D, v11, v28); // sha512su1 v2.2D, v11.2D, v28.2D + __ sha512h(v23, __ T2D, v16, v30); // sha512h q23, q16, v30.2D + __ sha512h2(v20, __ T2D, v20, v0); // sha512h2 q20, q20, v0.2D + __ sha512su0(v4, __ T2D, v19); // sha512su0 v4.2D, v19.2D + __ sha512su1(v24, __ T2D, v4, v20); // sha512su1 v24.2D, v4.2D, v20.2D // SVEBinaryImmOp - __ sve_add(z3, __ B, 10u); // add z3.b, z3.b, #0xa - __ sve_sub(z26, __ S, 150u); // sub z26.s, z26.s, #0x96 - __ sve_and(z14, __ H, 57343u); // and z14.h, z14.h, #0xdfff - __ sve_eor(z24, __ B, 191u); // eor z24.b, z24.b, #0xbf - __ sve_orr(z17, __ S, 4294966791u); // orr z17.s, z17.s, #0xfffffe07 + __ sve_add(z4, __ D, 210u); // add z4.d, z4.d, #0xd2 + __ sve_sub(z19, __ B, 71u); // sub z19.b, z19.b, #0x47 + __ sve_and(z8, __ H, 49663u); // and z8.h, z8.h, #0xc1ff + __ sve_eor(z31, __ S, 4294967231u); // eor z31.s, z31.s, #0xffffffbf + __ sve_orr(z1, __ H, 16368u); // orr z1.h, z1.h, #0x3ff0 // SVEBinaryImmOp - __ sve_add(z20, __ S, 3u); // add z20.s, z20.s, #0x3 - __ sve_sub(z4, __ S, 196u); // sub z4.s, z4.s, #0xc4 - __ sve_and(z4, __ S, 4286578691u); // and z4.s, z4.s, #0xff800003 - __ sve_eor(z25, __ S, 33553408u); // eor z25.s, z25.s, #0x1fffc00 - __ sve_orr(z8, __ H, 49663u); // orr z8.h, z8.h, #0xc1ff + __ sve_add(z0, __ H, 61u); // add z0.h, z0.h, #0x3d + __ sve_sub(z24, __ S, 36u); // sub z24.s, z24.s, #0x24 + __ sve_and(z27, __ B, 243u); // and z27.b, z27.b, #0xf3 + __ sve_eor(z24, __ H, 65534u); // eor z24.h, z24.h, #0xfffe + __ sve_orr(z22, __ S, 4294967293u); // orr z22.s, z22.s, #0xfffffffd // SVEBinaryImmOp - __ sve_add(z30, __ S, 36u); // add z30.s, z30.s, #0x24 - __ sve_sub(z30, __ B, 85u); // sub z30.b, z30.b, #0x55 - __ sve_and(z19, __ H, 4032u); // and z19.h, z19.h, #0xfc0 - __ sve_eor(z7, __ D, 274877904896u); // eor z7.d, z7.d, #0x3ffffff800 - __ sve_orr(z27, __ B, 243u); // orr z27.b, z27.b, #0xf3 + __ sve_add(z29, __ H, 113u); // add z29.h, z29.h, #0x71 + __ sve_sub(z20, __ B, 165u); // sub z20.b, z20.b, #0xa5 + __ sve_and(z28, __ H, 32256u); // and z28.h, z28.h, #0x7e00 + __ sve_eor(z12, __ S, 4287102855u); // eor z12.s, z12.s, #0xff87ff87 + __ sve_orr(z9, __ S, 3825205247u); // orr z9.s, z9.s, #0xe3ffffff // SVEBinaryImmOp - __ sve_add(z23, __ H, 132u); // add z23.h, z23.h, #0x84 - __ sve_sub(z30, __ S, 183u); // sub z30.s, z30.s, #0xb7 - __ sve_and(z20, __ D, 4503599627354112u); // and z20.d, z20.d, #0xfffffffffc000 - __ sve_eor(z13, __ S, 4042322160u); // eor z13.s, z13.s, #0xf0f0f0f0 - __ sve_orr(z28, __ H, 32256u); // orr z28.h, z28.h, #0x7e00 + __ sve_add(z18, __ S, 41u); // add z18.s, z18.s, #0x29 + __ sve_sub(z0, __ B, 98u); // sub z0.b, z0.b, #0x62 + __ sve_and(z8, __ H, 32768u); // and z8.h, z8.h, #0x8000 + __ sve_eor(z4, __ H, 508u); // eor z4.h, z4.h, #0x1fc + __ sve_orr(z0, __ H, 64512u); // orr z0.h, z0.h, #0xfc00 // SVEBinaryImmOp - __ sve_add(z11, __ S, 13u); // add z11.s, z11.s, #0xd - __ sve_sub(z24, __ H, 159u); // sub z24.h, z24.h, #0x9f - __ sve_and(z13, __ S, 2151677951u); // and z13.s, z13.s, #0x803fffff - __ sve_eor(z4, __ B, 124u); // eor z4.b, z4.b, #0x7c - __ sve_orr(z7, __ H, 32768u); // orr z7.h, z7.h, #0x8000 + __ sve_add(z3, __ B, 79u); // add z3.b, z3.b, #0x4f + __ sve_sub(z19, __ D, 84u); // sub z19.d, z19.d, #0x54 + __ sve_and(z24, __ B, 62u); // and z24.b, z24.b, #0x3e + __ sve_eor(z24, __ D, 18428729675200069887u); // eor z24.d, z24.d, #0xffc00000000000ff + __ sve_orr(z11, __ D, 17296056810822168583u); // orr z11.d, z11.d, #0xf007f007f007f007 // SVEBinaryImmOp - __ sve_add(z4, __ H, 243u); // add z4.h, z4.h, #0xf3 - __ sve_sub(z5, __ B, 86u); // sub z5.b, z5.b, #0x56 - __ sve_and(z21, __ D, 8064u); // and z21.d, z21.d, #0x1f80 - __ sve_eor(z9, __ S, 130023424u); // eor z9.s, z9.s, #0x7c00000 - __ sve_orr(z24, __ B, 62u); // orr z24.b, z24.b, #0x3e + __ sve_add(z31, __ S, 115u); // add z31.s, z31.s, #0x73 + __ sve_sub(z3, __ D, 134u); // sub z3.d, z3.d, #0x86 + __ sve_and(z22, __ S, 4042322160u); // and z22.s, z22.s, #0xf0f0f0f0 + __ sve_eor(z3, __ B, 225u); // eor z3.b, z3.b, #0xe1 + __ sve_orr(z9, __ S, 4164941887u); // orr z9.s, z9.s, #0xf83ff83f // SVEVectorOp - __ sve_add(z23, __ S, z28, z13); // add z23.s, z28.s, z13.s - __ sve_sub(z10, __ S, z26, z12); // sub z10.s, z26.s, z12.s - __ sve_fadd(z30, __ S, z17, z14); // fadd z30.s, z17.s, z14.s - __ sve_fmul(z29, __ D, z16, z21); // fmul z29.d, z16.d, z21.d - __ sve_fsub(z7, __ S, z19, z2); // fsub z7.s, z19.s, z2.s - __ sve_abs(z26, __ S, p4, z9); // abs z26.s, p4/m, z9.s - __ sve_add(z17, __ B, p5, z0); // add z17.b, p5/m, z17.b, z0.b - __ sve_and(z2, __ B, p6, z14); // and z2.b, p6/m, z2.b, z14.b - __ sve_asr(z11, __ S, p5, z14); // asr z11.s, p5/m, z11.s, z14.s - __ sve_bic(z29, __ B, p3, z3); // bic z29.b, p3/m, z29.b, z3.b - __ sve_clz(z22, __ D, p2, z3); // clz z22.d, p2/m, z3.d - __ sve_cnt(z27, __ S, p0, z19); // cnt z27.s, p0/m, z19.s - __ sve_eor(z7, __ H, p6, z21); // eor z7.h, p6/m, z7.h, z21.h - __ sve_lsl(z5, __ B, p2, z25); // lsl z5.b, p2/m, z5.b, z25.b - __ sve_lsr(z21, __ B, p4, z17); // lsr z21.b, p4/m, z21.b, z17.b - __ sve_mul(z3, __ H, p2, z19); // mul z3.h, p2/m, z3.h, z19.h - __ sve_neg(z7, __ S, p3, z14); // neg z7.s, p3/m, z14.s - __ sve_not(z17, __ D, p2, z13); // not z17.d, p2/m, z13.d - __ sve_orr(z17, __ H, p7, z17); // orr z17.h, p7/m, z17.h, z17.h - __ sve_rbit(z15, __ S, p3, z26); // rbit z15.s, p3/m, z26.s - __ sve_revb(z27, __ H, p5, z7); // revb z27.h, p5/m, z7.h - __ sve_smax(z5, __ H, p7, z27); // smax z5.h, p7/m, z5.h, z27.h - __ sve_smin(z0, __ S, p3, z24); // smin z0.s, p3/m, z0.s, z24.s - __ sve_sub(z20, __ S, p0, z3); // sub z20.s, p0/m, z20.s, z3.s - __ sve_fabs(z25, __ D, p1, z25); // fabs z25.d, p1/m, z25.d - __ sve_fadd(z17, __ S, p4, z1); // fadd z17.s, p4/m, z17.s, z1.s - __ sve_fdiv(z14, __ S, p7, z13); // fdiv z14.s, p7/m, z14.s, z13.s - __ sve_fmax(z17, __ D, p0, z30); // fmax z17.d, p0/m, z17.d, z30.d - __ sve_fmin(z22, __ S, p5, z29); // fmin z22.s, p5/m, z22.s, z29.s - __ sve_fmul(z8, __ S, p0, z0); // fmul z8.s, p0/m, z8.s, z0.s - __ sve_fneg(z23, __ D, p5, z0); // fneg z23.d, p5/m, z0.d - __ sve_frintm(z25, __ S, p6, z23); // frintm z25.s, p6/m, z23.s - __ sve_frintn(z21, __ S, p5, z1); // frintn z21.s, p5/m, z1.s - __ sve_frintp(z10, __ D, p5, z11); // frintp z10.d, p5/m, z11.d - __ sve_fsqrt(z23, __ D, p6, z8); // fsqrt z23.d, p6/m, z8.d - __ sve_fsub(z17, __ D, p5, z19); // fsub z17.d, p5/m, z17.d, z19.d - __ sve_fmad(z4, __ D, p5, z13, z30); // fmad z4.d, p5/m, z13.d, z30.d - __ sve_fmla(z30, __ D, p7, z25, z17); // fmla z30.d, p7/m, z25.d, z17.d - __ sve_fmls(z14, __ D, p2, z12, z28); // fmls z14.d, p2/m, z12.d, z28.d - __ sve_fmsb(z5, __ S, p0, z13, z13); // fmsb z5.s, p0/m, z13.s, z13.s - __ sve_fnmad(z7, __ S, p2, z11, z19); // fnmad z7.s, p2/m, z11.s, z19.s - __ sve_fnmsb(z25, __ D, p3, z2, z3); // fnmsb z25.d, p3/m, z2.d, z3.d - __ sve_fnmla(z0, __ D, p5, z5, z20); // fnmla z0.d, p5/m, z5.d, z20.d - __ sve_fnmls(z28, __ S, p3, z13, z8); // fnmls z28.s, p3/m, z13.s, z8.s - __ sve_mla(z29, __ B, p0, z14, z27); // mla z29.b, p0/m, z14.b, z27.b - __ sve_mls(z3, __ H, p6, z8, z24); // mls z3.h, p6/m, z8.h, z24.h - __ sve_and(z1, z25, z10); // and z1.d, z25.d, z10.d - __ sve_eor(z1, z20, z25); // eor z1.d, z20.d, z25.d - __ sve_orr(z28, z19, z16); // orr z28.d, z19.d, z16.d - __ sve_bic(z27, z13, z1); // bic z27.d, z13.d, z1.d - __ sve_uzp1(z11, __ B, z9, z1); // uzp1 z11.b, z9.b, z1.b - __ sve_uzp2(z1, __ H, z27, z26); // uzp2 z1.h, z27.h, z26.h - __ sve_fabd(z2, __ D, p1, z29); // fabd z2.d, p1/m, z2.d, z29.d - __ sve_bext(z24, __ D, z2, z2); // bext z24.d, z2.d, z2.d - __ sve_bdep(z3, __ H, z25, z28); // bdep z3.h, z25.h, z28.h - __ sve_eor3(z3, z22, z13); // eor3 z3.d, z3.d, z22.d, z13.d + __ sve_add(z0, __ D, z4, z2); // add z0.d, z4.d, z2.d + __ sve_sub(z14, __ S, z6, z11); // sub z14.s, z6.s, z11.s + __ sve_fadd(z14, __ S, z17, z30); // fadd z14.s, z17.s, z30.s + __ sve_fmul(z3, __ S, z3, z23); // fmul z3.s, z3.s, z23.s + __ sve_fsub(z3, __ S, z24, z28); // fsub z3.s, z24.s, z28.s + __ sve_abs(z19, __ D, p5, z7); // abs z19.d, p5/m, z7.d + __ sve_add(z21, __ H, p3, z5); // add z21.h, p3/m, z21.h, z5.h + __ sve_and(z26, __ S, p1, z22); // and z26.s, p1/m, z26.s, z22.s + __ sve_asr(z17, __ H, p0, z3); // asr z17.h, p0/m, z17.h, z3.h + __ sve_bic(z20, __ H, p3, z8); // bic z20.h, p3/m, z20.h, z8.h + __ sve_clz(z14, __ H, p4, z17); // clz z14.h, p4/m, z17.h + __ sve_cnt(z13, __ D, p6, z18); // cnt z13.d, p6/m, z18.d + __ sve_eor(z19, __ H, p2, z16); // eor z19.h, p2/m, z19.h, z16.h + __ sve_lsl(z27, __ S, p5, z28); // lsl z27.s, p5/m, z27.s, z28.s + __ sve_lsr(z8, __ D, p2, z5); // lsr z8.d, p2/m, z8.d, z5.d + __ sve_mul(z28, __ H, p2, z0); // mul z28.h, p2/m, z28.h, z0.h + __ sve_neg(z25, __ B, p5, z21); // neg z25.b, p5/m, z21.b + __ sve_not(z3, __ B, p5, z26); // not z3.b, p5/m, z26.b + __ sve_orr(z26, __ S, p7, z19); // orr z26.s, p7/m, z26.s, z19.s + __ sve_rbit(z1, __ D, p3, z14); // rbit z1.d, p3/m, z14.d + __ sve_revb(z14, __ H, p0, z18); // revb z14.h, p0/m, z18.h + __ sve_smax(z31, __ S, p5, z23); // smax z31.s, p5/m, z31.s, z23.s + __ sve_smin(z30, __ B, p3, z8); // smin z30.b, p3/m, z30.b, z8.b + __ sve_sub(z0, __ S, p3, z23); // sub z0.s, p3/m, z0.s, z23.s + __ sve_fabs(z0, __ D, p4, z26); // fabs z0.d, p4/m, z26.d + __ sve_fadd(z24, __ D, p3, z22); // fadd z24.d, p3/m, z24.d, z22.d + __ sve_fdiv(z2, __ D, p0, z11); // fdiv z2.d, p0/m, z2.d, z11.d + __ sve_fmax(z12, __ D, p5, z24); // fmax z12.d, p5/m, z12.d, z24.d + __ sve_fmin(z9, __ D, p7, z17); // fmin z9.d, p7/m, z9.d, z17.d + __ sve_fmul(z20, __ D, p5, z4); // fmul z20.d, p5/m, z20.d, z4.d + __ sve_fneg(z13, __ D, p7, z22); // fneg z13.d, p7/m, z22.d + __ sve_frintm(z31, __ D, p6, z18); // frintm z31.d, p6/m, z18.d + __ sve_frintn(z15, __ D, p2, z13); // frintn z15.d, p2/m, z13.d + __ sve_frintp(z20, __ S, p1, z1); // frintp z20.s, p1/m, z1.s + __ sve_fsqrt(z14, __ S, p0, z7); // fsqrt z14.s, p0/m, z7.s + __ sve_fsub(z12, __ D, p4, z4); // fsub z12.d, p4/m, z12.d, z4.d + __ sve_fmad(z15, __ S, p0, z3, z30); // fmad z15.s, p0/m, z3.s, z30.s + __ sve_fmla(z20, __ D, p1, z20, z31); // fmla z20.d, p1/m, z20.d, z31.d + __ sve_fmls(z13, __ D, p3, z9, z14); // fmls z13.d, p3/m, z9.d, z14.d + __ sve_fmsb(z1, __ S, p3, z28, z3); // fmsb z1.s, p3/m, z28.s, z3.s + __ sve_fnmad(z26, __ S, p2, z25, z9); // fnmad z26.s, p2/m, z25.s, z9.s + __ sve_fnmsb(z26, __ D, p2, z14, z1); // fnmsb z26.d, p2/m, z14.d, z1.d + __ sve_fnmla(z26, __ D, p1, z29, z20); // fnmla z26.d, p1/m, z29.d, z20.d + __ sve_fnmls(z6, __ D, p7, z13, z1); // fnmls z6.d, p7/m, z13.d, z1.d + __ sve_mla(z11, __ B, p2, z1, z1); // mla z11.b, p2/m, z1.b, z1.b + __ sve_mls(z27, __ B, p6, z15, z2); // mls z27.b, p6/m, z15.b, z2.b + __ sve_and(z30, z17, z25); // and z30.d, z17.d, z25.d + __ sve_eor(z2, z24, z3); // eor z2.d, z24.d, z3.d + __ sve_orr(z29, z13, z3); // orr z29.d, z13.d, z3.d + __ sve_bic(z14, z16, z28); // bic z14.d, z16.d, z28.d + __ sve_uzp1(z4, __ S, z11, z27); // uzp1 z4.s, z11.s, z27.s + __ sve_uzp2(z2, __ D, z16, z1); // uzp2 z2.d, z16.d, z1.d + __ sve_fabd(z7, __ D, p5, z31); // fabd z7.d, p5/m, z7.d, z31.d + __ sve_bext(z16, __ S, z10, z22); // bext z16.s, z10.s, z22.s + __ sve_bdep(z29, __ B, z7, z22); // bdep z29.b, z7.b, z22.b + __ sve_eor3(z12, z24, z11); // eor3 z12.d, z12.d, z24.d, z11.d // SVEReductionOp - __ sve_andv(v27, __ H, p4, z4); // andv h27, p4, z4.h - __ sve_orv(v26, __ S, p4, z2); // orv s26, p4, z2.s - __ sve_eorv(v1, __ S, p7, z7); // eorv s1, p7, z7.s - __ sve_smaxv(v30, __ H, p7, z16); // smaxv h30, p7, z16.h - __ sve_sminv(v21, __ B, p4, z28); // sminv b21, p4, z28.b - __ sve_fminv(v21, __ D, p1, z12); // fminv d21, p1, z12.d - __ sve_fmaxv(v11, __ S, p2, z10); // fmaxv s11, p2, z10.s - __ sve_fadda(v0, __ D, p1, z22); // fadda d0, p1, d0, z22.d - __ sve_uaddv(v20, __ H, p1, z3); // uaddv d20, p1, z3.h + __ sve_andv(v11, __ B, p2, z0); // andv b11, p2, z0.b + __ sve_orv(v23, __ B, p5, z20); // orv b23, p5, z20.b + __ sve_eorv(v3, __ B, p3, z15); // eorv b3, p3, z15.b + __ sve_smaxv(v30, __ B, p6, z27); // smaxv b30, p6, z27.b + __ sve_sminv(v21, __ D, p6, z10); // sminv d21, p6, z10.d + __ sve_fminv(v3, __ S, p6, z4); // fminv s3, p6, z4.s + __ sve_fmaxv(v6, __ S, p0, z21); // fmaxv s6, p0, z21.s + __ sve_fadda(v25, __ D, p6, z30); // fadda d25, p6, d25, z30.d + __ sve_uaddv(v31, __ H, p4, z1); // uaddv d31, p4, z1.h + +// AddWideNEONOp + __ saddwv(v12, v13, __ T8H, v14, __ T8B); // saddw v12.8H, v13.8H, v14.8B + __ saddwv2(v30, v31, __ T8H, v0, __ T16B); // saddw2 v30.8H, v31.8H, v0.16B + __ saddwv(v13, v14, __ T4S, v15, __ T4H); // saddw v13.4S, v14.4S, v15.4H + __ saddwv2(v8, v9, __ T4S, v10, __ T8H); // saddw2 v8.4S, v9.4S, v10.8H + __ saddwv(v25, v26, __ T2D, v27, __ T2S); // saddw v25.2D, v26.2D, v27.2S + __ saddwv2(v29, v30, __ T2D, v31, __ T4S); // saddw2 v29.2D, v30.2D, v31.4S + __ uaddwv(v1, v2, __ T8H, v3, __ T8B); // uaddw v1.8H, v2.8H, v3.8B + __ uaddwv2(v31, v0, __ T8H, v1, __ T16B); // uaddw2 v31.8H, v0.8H, v1.16B + __ uaddwv(v23, v24, __ T4S, v25, __ T4H); // uaddw v23.4S, v24.4S, v25.4H + __ uaddwv2(v31, v0, __ T4S, v1, __ T8H); // uaddw2 v31.4S, v0.4S, v1.8H + __ uaddwv(v20, v21, __ T2D, v22, __ T2S); // uaddw v20.2D, v21.2D, v22.2S + __ uaddwv2(v0, v1, __ T2D, v2, __ T4S); // uaddw2 v0.2D, v1.2D, v2.4S __ bind(forth); @@ -1298,30 +1327,30 @@ 0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061, 0x120cb166, 0x321764bc, 0x52174681, 0x720c0227, 0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01, - 0x14000000, 0x17ffffd7, 0x14000428, 0x94000000, - 0x97ffffd4, 0x94000425, 0x3400000a, 0x34fffa2a, - 0x3400844a, 0x35000008, 0x35fff9c8, 0x350083e8, - 0xb400000b, 0xb4fff96b, 0xb400838b, 0xb500001d, - 0xb5fff91d, 0xb500833d, 0x10000013, 0x10fff8b3, - 0x100082d3, 0x90000013, 0x36300016, 0x3637f836, - 0x36308256, 0x3758000c, 0x375ff7cc, 0x375881ec, + 0x14000000, 0x17ffffd7, 0x14000441, 0x94000000, + 0x97ffffd4, 0x9400043e, 0x3400000a, 0x34fffa2a, + 0x3400876a, 0x35000008, 0x35fff9c8, 0x35008708, + 0xb400000b, 0xb4fff96b, 0xb40086ab, 0xb500001d, + 0xb5fff91d, 0xb500865d, 0x10000013, 0x10fff8b3, + 0x100085f3, 0x90000013, 0x36300016, 0x3637f836, + 0x36308576, 0x3758000c, 0x375ff7cc, 0x3758850c, 0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc, 0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f, 0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016, 0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0, - 0x54007fc0, 0x54000001, 0x54fff541, 0x54007f61, - 0x54000002, 0x54fff4e2, 0x54007f02, 0x54000002, - 0x54fff482, 0x54007ea2, 0x54000003, 0x54fff423, - 0x54007e43, 0x54000003, 0x54fff3c3, 0x54007de3, - 0x54000004, 0x54fff364, 0x54007d84, 0x54000005, - 0x54fff305, 0x54007d25, 0x54000006, 0x54fff2a6, - 0x54007cc6, 0x54000007, 0x54fff247, 0x54007c67, - 0x54000008, 0x54fff1e8, 0x54007c08, 0x54000009, - 0x54fff189, 0x54007ba9, 0x5400000a, 0x54fff12a, - 0x54007b4a, 0x5400000b, 0x54fff0cb, 0x54007aeb, - 0x5400000c, 0x54fff06c, 0x54007a8c, 0x5400000d, - 0x54fff00d, 0x54007a2d, 0x5400000e, 0x54ffefae, - 0x540079ce, 0x5400000f, 0x54ffef4f, 0x5400796f, + 0x540082e0, 0x54000001, 0x54fff541, 0x54008281, + 0x54000002, 0x54fff4e2, 0x54008222, 0x54000002, + 0x54fff482, 0x540081c2, 0x54000003, 0x54fff423, + 0x54008163, 0x54000003, 0x54fff3c3, 0x54008103, + 0x54000004, 0x54fff364, 0x540080a4, 0x54000005, + 0x54fff305, 0x54008045, 0x54000006, 0x54fff2a6, + 0x54007fe6, 0x54000007, 0x54fff247, 0x54007f87, + 0x54000008, 0x54fff1e8, 0x54007f28, 0x54000009, + 0x54fff189, 0x54007ec9, 0x5400000a, 0x54fff12a, + 0x54007e6a, 0x5400000b, 0x54fff0cb, 0x54007e0b, + 0x5400000c, 0x54fff06c, 0x54007dac, 0x5400000d, + 0x54fff00d, 0x54007d4d, 0x5400000e, 0x54ffefae, + 0x54007cee, 0x5400000f, 0x54ffef4f, 0x54007c8f, 0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60, 0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f, 0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf, @@ -1346,23 +1375,23 @@ 0xb81b1022, 0x381ea354, 0x79002fd7, 0xf85cf39a, 0xb8580309, 0x385e218c, 0x784051e1, 0x389e11d8, 0x789fa1f8, 0x79c01865, 0xb881131b, 0xfc5dd3ad, - 0xbc5d1136, 0xfc00900b, 0xbc181014, 0xf818ec7d, + 0xbc5d1137, 0xfc00900b, 0xbc181015, 0xf818ec7d, 0xb81b8c91, 0x381efc40, 0x78007c3d, 0xf857beb0, 0xb8413dd4, 0x385fddd6, 0x78409e2f, 0x389eddea, 0x789e7d94, 0x78de3d55, 0xb8805c13, 0xfc5cadc0, - 0xbc428c23, 0xfc1a2dc4, 0xbc1caf91, 0xf81475f6, + 0xbc428c23, 0xfc1a2dc4, 0xbc1caf92, 0xf81475f6, 0xb81f95d1, 0x381e757e, 0x78014561, 0xf8402436, 0xb85896e2, 0x385f4763, 0x785db4f0, 0x3880374f, 0x789e25e7, 0x78dd0563, 0xb88166f9, 0xfc529540, - 0xbc4374d1, 0xfc1166ad, 0xbc1ba6c0, 0xf820ea7b, + 0xbc4374d3, 0xfc1166ae, 0xbc1ba6c0, 0xf820ea7b, 0xb82d68c8, 0x38367a04, 0x782f4b59, 0xf878c8a4, 0xb8674a24, 0x386b78f1, 0x78776bc0, 0x38a15aca, - 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, 0xfc6ecbbd, - 0xbc65d8a8, 0xfc2de918, 0xbc3a7b11, 0xf91f1193, + 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, 0xfc6ecbbe, + 0xbc65d8a8, 0xfc2de919, 0xbc3a7b11, 0xf91f1193, 0xb91ed5f7, 0x391ec9bd, 0x79182ceb, 0xf95d4b0a, 0xb9581010, 0x395fc034, 0x795fb221, 0x399d8731, 0x799efb3b, 0x79dd1a2e, 0xb998e4ea, 0xfd583723, - 0xbd5ea12c, 0xfd18dc37, 0xbd1b0e83, 0x58ffdaa2, + 0xbd5ea12c, 0xfd18dc38, 0xbd1b0e83, 0x58ffdaa2, 0x1800001d, 0xf885d1c0, 0xd8ffda40, 0xf8a77820, 0xf9980220, 0x1a030301, 0x3a140311, 0x5a0d000b, 0x7a07015c, 0x9a1001e4, 0xba140182, 0xda0d01bd, @@ -1383,187 +1412,193 @@ 0x9ad521f7, 0x9adb263c, 0x9ac0286a, 0x9ac92f27, 0x9bdd7de6, 0x9b427d4f, 0x1b0b2cf1, 0x1b1ddcf7, 0x9b0b2f6e, 0x9b0cbf04, 0x9b2b728e, 0x9b2cdd6d, - 0x9bae275e, 0x9ba7954d, 0x7ea3d5fd, 0x1e2f098b, - 0x1e311bde, 0x1e2f2a93, 0x1e35392f, 0x7efbd522, - 0x1e7e0ba7, 0x1e621831, 0x1e632946, 0x1e673978, - 0x1f000d61, 0x1f06db91, 0x1f3b6806, 0x1f2770a2, - 0x1f4d2f2b, 0x1f48c677, 0x1f744f35, 0x1f7d5851, - 0x1e2042a8, 0x1e20c293, 0x1e21422b, 0x1e21c0d4, - 0x1e22c06f, 0x1e23c383, 0x1ee24363, 0x1e6041ce, - 0x1e60c18a, 0x1e61422b, 0x1e61c32a, 0x1e6240e7, - 0x1e38038e, 0x9e3802c0, 0x1e780180, 0x9e7801b7, - 0x1e2200ed, 0x9e2200ee, 0x1e620288, 0x9e620391, - 0x1e24021e, 0x9e640122, 0x1e300290, 0x9e70009d, - 0x1e260341, 0x9e6602f8, 0x1e2702ae, 0x9e6700ac, - 0x1e382180, 0x1e7d2300, 0x1e202368, 0x1e6022a8, + 0x9bae275e, 0x9ba7954d, 0x7ea3d5fe, 0x1e30098c, + 0x1e321bff, 0x1e302ab3, 0x1e35394f, 0x7efcd542, + 0x1e7f0bc7, 0x1e621832, 0x1e632946, 0x1e673979, + 0x1f000d81, 0x1f06dfb3, 0x1f3c6c06, 0x1f2774a2, + 0x1f4d332c, 0x1f48ca78, 0x1f755356, 0x1f7e5853, + 0x1e2042c8, 0x1e20c2b3, 0x1e21424c, 0x1e21c0d5, + 0x1e22c070, 0x1e23c3a3, 0x1ee24383, 0x1e6041cf, + 0x1e60c1aa, 0x1e61424c, 0x1e61c34a, 0x1e6240e7, + 0x1e3803ae, 0x9e3802e0, 0x1e780180, 0x9e7801d7, + 0x1e2200ed, 0x9e2200ef, 0x1e620289, 0x9e620393, + 0x1e24021e, 0x9e640122, 0x1e3002b0, 0x9e70009d, + 0x1e260361, 0x9e660318, 0x1e2702ae, 0x9e6700ad, + 0x1e392180, 0x1e7e2320, 0x1e202388, 0x1e6022a8, 0x293a1796, 0x29426e73, 0x697c68fc, 0xa93d0486, 0xa97b5eba, 0x29b47934, 0x29c2534d, 0x69f62dbd, 0xa9bd54bb, 0xa9c503c6, 0x28a63e13, 0x28e25d2c, 0x68c469e0, 0xa8b34748, 0xa8f51c59, 0x28264433, 0x285036c0, 0xa8005f7d, 0xa872290b, 0x0c407160, - 0x4cdfa350, 0x0cd16f55, 0x4cdf27ba, 0x0d40c0d5, - 0x4ddfcbad, 0x0dd0cd95, 0x4c408c01, 0x0cdf86a9, - 0x4d60c327, 0x0dffc928, 0x4deecd89, 0x4cd14887, - 0x0c404a37, 0x4d40e6c3, 0x4ddfe84c, 0x0dcced4f, - 0x4cdf0444, 0x0ccb0286, 0x0d60e18b, 0x0dffe62f, - 0x0df0eb2e, 0x0e31bab4, 0x4e31b841, 0x0e71baf6, + 0x4cdfa350, 0x0cd16f56, 0x4cdf27bb, 0x0d40c0d6, + 0x4ddfcbae, 0x0dd0cd96, 0x4c408c01, 0x0cdf86aa, + 0x4d60c327, 0x0dffc929, 0x4deecd89, 0x4cd14887, + 0x0c404a37, 0x4d40e6c4, 0x4ddfe84d, 0x0dcced50, + 0x4cdf0444, 0x0ccb0286, 0x0d60e18c, 0x0dffe630, + 0x0df0eb2e, 0x0e31bab4, 0x4e31b841, 0x0e71bb17, 0x4e71bbfe, 0x4eb1b9ee, 0x0e30a862, 0x4e30a8e6, - 0x0e70a883, 0x4e70a907, 0x4eb0ab38, 0x6e30f820, - 0x0e31ab9b, 0x2e31abdd, 0x4e31a8c5, 0x6e31a8c5, - 0x0e71abdd, 0x2e71a98b, 0x4e71ab59, 0x6e71a820, - 0x4eb1abfe, 0x6eb1a820, 0x6eb0fa51, 0x7e30fbbc, - 0x7e70fb59, 0x7eb0f949, 0x7ef0fb59, 0x0ea0c9ac, - 0x4ea0ca0f, 0x4ee0c98b, 0x2ea0c96a, 0x6ea0ca51, - 0x6ee0cb38, 0x0ea0dad5, 0x4ea0db17, 0x4ee0d820, - 0x0ea0ea30, 0x4ea0e96a, 0x4ee0e8e6, 0x2ea0dbbc, - 0x6ea0d8e6, 0x6ee0d8c5, 0x0e20b8c5, 0x4e20bab4, - 0x0e60ba51, 0x4e60ba0f, 0x0ea0ba51, 0x4ea0bbdd, - 0x4ee0bb7a, 0x0ea0fbbc, 0x4ea0f841, 0x4ee0fb9b, - 0x2ea0f820, 0x6ea0fab4, 0x6ee0fbbc, 0x2ea1fa0f, - 0x6ea1f9ac, 0x6ee1f96a, 0x2e205bbc, 0x6e205bbc, + 0x0e70a883, 0x4e70a928, 0x4eb0ab59, 0x6e30f820, + 0x0e31ab9b, 0x2e31abfe, 0x4e31a8c5, 0x6e31a8c5, + 0x0e71abfe, 0x2e71a98b, 0x4e71ab59, 0x6e71a820, + 0x4eb1a81f, 0x6eb1a820, 0x6eb0fa93, 0x7e30fbdd, + 0x7e70fb7a, 0x7eb0f949, 0x7ef0fb7a, 0x0ea0c9ac, + 0x4ea0ca0f, 0x4ee0c98b, 0x2ea0c98b, 0x6ea0ca72, + 0x6ee0cb59, 0x0ea0daf6, 0x4ea0db38, 0x4ee0d820, + 0x0ea0ea51, 0x4ea0e98b, 0x4ee0e8e6, 0x2ea0dbdd, + 0x6ea0d8e6, 0x6ee0d8c5, 0x0e20b8c5, 0x4e20bad5, + 0x0e60ba93, 0x4e60ba30, 0x0ea0ba72, 0x4ea0bbfe, + 0x4ee0bb9b, 0x0ea0fbbc, 0x4ea0f841, 0x4ee0fbbc, + 0x2ea0f841, 0x6ea0fab4, 0x6ee0fbdd, 0x2ea1fa30, + 0x6ea1f9cd, 0x6ee1f96a, 0x2e205bdd, 0x6e205bdd, 0x0e351e93, 0x4e381ef6, 0x0eac1d6a, 0x4ea61ca4, - 0x2e201ffe, 0x6e361eb4, 0x0e2a8528, 0x4e2087fe, - 0x0e738651, 0x4e6c856a, 0x0ebd879b, 0x4ea48462, - 0x4efa8738, 0x0e26d4a4, 0x4e25d483, 0x4e6ad528, - 0x2e3886f6, 0x6e338651, 0x2e6f85cd, 0x6e6684a4, - 0x2ebe87bc, 0x6eb98717, 0x6ef786d5, 0x0ebbd759, - 0x4ebad738, 0x4ee5d483, 0x0e399f17, 0x4e3c9f7a, - 0x0e799f17, 0x4e709dee, 0x0eb79ed5, 0x4ea59c83, - 0x2eb9d717, 0x6eaad528, 0x6efad738, 0x2e35d693, - 0x6e31d60f, 0x6e72d630, 0x2e24dc62, 0x6e23dc41, + 0x2e211c1f, 0x6e371ed5, 0x0e2a8528, 0x4e21841f, + 0x0e758693, 0x4e6c856a, 0x0ebe87bc, 0x4ea48462, + 0x4efb8759, 0x0e27d4c5, 0x4e25d483, 0x4e6ad528, + 0x2e3886f6, 0x6e358693, 0x2e6f85cd, 0x6e6784c5, + 0x2ebf87dd, 0x6eba8738, 0x6ef786d5, 0x0ebcd77a, + 0x4ebad738, 0x4ee5d483, 0x0e3a9f38, 0x4e3c9f7a, + 0x0e799f17, 0x4e719e0f, 0x0eb79ed5, 0x4ea59c83, + 0x2ebad738, 0x6eaad528, 0x6efbd759, 0x2e36d6b4, + 0x6e32d630, 0x6e73d651, 0x2e24dc62, 0x6e23dc41, 0x6e62dc20, 0x0e7a9738, 0x4e6694a4, 0x0ea59483, - 0x4ead958b, 0x0e20cffe, 0x4e3dcf9b, 0x4e6bcd49, - 0x2e7b9759, 0x6e649462, 0x2eae95ac, 0x6eb39651, - 0x0ea0cffe, 0x4ea3cc41, 0x4eeecdac, 0x2e3effbc, - 0x6e22fc20, 0x6e73fe51, 0x0e2e65ac, 0x4e336651, - 0x0e7766d5, 0x4e6e65ac, 0x0ebd679b, 0x4ebf67dd, - 0x0e20a7fe, 0x4e23a441, 0x0e7ba759, 0x4e7da79b, - 0x0ea6a4a4, 0x4ebfa7dd, 0x0e25f483, 0x4e28f4e6, - 0x4e7ff7dd, 0x0e3b6f59, 0x4e336e51, 0x0e6a6d28, - 0x4e696d07, 0x0eae6dac, 0x4ea26c20, 0x0e35ae93, - 0x4e23ac41, 0x0e79af17, 0x4e64ac62, 0x0ea2ac20, - 0x4eaaad28, 0x0eb9f717, 0x4ebbf759, 0x4ef1f60f, - 0x2ebfefdd, 0x6ea5ec83, 0x6eeced6a, 0x0e3836f6, - 0x4e2c356a, 0x0e6634a4, 0x4e733651, 0x0ea33441, - 0x4ead358b, 0x4ee93507, 0x0e2c3d6a, 0x4e313e0f, - 0x0e723e30, 0x4e643c62, 0x0eab3d49, 0x4ead3d8b, - 0x4eee3dac, 0x2e308dee, 0x6e2f8dcd, 0x2e648c62, - 0x6e688ce6, 0x2eb58e93, 0x6ebb8f59, 0x6ef18e0f, - 0x2e2634a4, 0x6e243462, 0x2e6634a4, 0x6e6d358b, - 0x2eb33651, 0x6eb636b4, 0x6ef23630, 0x2e333e51, - 0x6e2c3d6a, 0x2e763eb4, 0x6e783ef6, 0x2eae3dac, - 0x6ebb3f59, 0x6ef93f17, 0x0e3ee7bc, 0x4e30e5ee, - 0x4e6ce56a, 0x2ebae738, 0x6ea3e441, 0x6eede58b, - 0x2e20e7fe, 0x6e2ce56a, 0x6e71e60f, 0x65922c43, - 0x65d02219, 0x65d02560, 0x65d13dc4, 0x65913690, - 0x65d33b6b, 0x2500948c, 0x254c08bf, 0x25831f87, - 0x254f30af, 0x259c3359, 0x25019d35, 0x24eac76d, - 0x2431993a, 0x242f7ed8, 0x24a2f62b, 0xba5fd3e3, - 0x3a5f03e5, 0xfa411be4, 0x7a42cbe2, 0x93df03ff, - 0xc820ffff, 0x8822fc7f, 0xc8247cbf, 0x88267fff, - 0x4e010fe0, 0x5e040420, 0x4e081fe1, 0x4e0c1fe1, - 0x4e0a1fe1, 0x4e071fe1, 0x4e042c20, 0x4e062c20, - 0x4e052c20, 0x4e083c20, 0x0e0c3c20, 0x0e0a3c20, - 0x0e073c20, 0x9eae0020, 0x0f03f409, 0x6f03f40e, - 0x4cc0ac3f, 0x0ea1b820, 0x4e21c862, 0x4e61b8a4, - 0x05a08020, 0x05104fe0, 0x05505001, 0x05906fe2, - 0x05d03005, 0x05101fea, 0x05901feb, 0x04b0e3e0, - 0x0470e7e1, 0x042f9c20, 0x043f9c35, 0x047f9c20, - 0x04ff9c20, 0x04299420, 0x04319160, 0x0461943e, - 0x04a19020, 0x04038100, 0x040381a0, 0x040387e1, - 0x04438be2, 0x04c38fe3, 0x040181e0, 0x04018100, - 0x04018621, 0x04418b22, 0x04418822, 0x04818c23, - 0x040081e0, 0x04008120, 0x04008761, 0x04008621, - 0x04408822, 0x04808c23, 0x042053ff, 0x047f5401, - 0x25208028, 0x2538cfe0, 0x2578d001, 0x25b8efe2, - 0x25f8f007, 0x2538dfea, 0x25b8dfeb, 0xa400a3e0, - 0xa420a7e0, 0xa4484be0, 0xa467afe0, 0xa4a8a7ea, - 0xa547a814, 0xa4084ffe, 0xa55c53e0, 0xa5e1540b, - 0xe400fbf6, 0xe408ffff, 0xe420e7e0, 0xe4484be0, - 0xe460efe0, 0xe547e400, 0xe4014be0, 0xe4a84fe0, - 0xe5f15000, 0x858043e0, 0x85a043ff, 0xe59f5d08, - 0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, 0x04e0e3ec, - 0x25104042, 0x25104871, 0x25904861, 0x25904c92, - 0x05344020, 0x05744041, 0x05b44062, 0x05f44083, - 0x252c8840, 0x253c1420, 0x25681572, 0x25a21ce3, - 0x25ea1e34, 0x253c0421, 0x25680572, 0x25a20ce3, - 0x25ea0e34, 0x0522c020, 0x05e6c0a4, 0x2401a001, - 0x2443a051, 0x24858881, 0x24c78cd1, 0x24850891, - 0x24c70cc1, 0x250f9001, 0x25508051, 0x25802491, - 0x25df28c1, 0x25850c81, 0x251e10d1, 0x65816001, - 0x65c36051, 0x65854891, 0x65c74cc1, 0x05733820, - 0x05b238a4, 0x05f138e6, 0x0570396a, 0x65d0a001, - 0x65d6a443, 0x65d4a826, 0x6594ac26, 0x6554ac26, - 0x6556ac26, 0x6552ac26, 0x65cbac85, 0x65caac01, - 0x6589ac85, 0x6588ac01, 0x65c9ac85, 0x65c8ac01, - 0x65dea833, 0x659ca509, 0x65d8a801, 0x65dcac01, - 0x655cb241, 0x0520a1e0, 0x0521a601, 0x052281e0, - 0x05238601, 0x04a14026, 0x042244a6, 0x046344a6, - 0x04a444a6, 0x04e544a7, 0x0568aca7, 0x05b23230, - 0x853040af, 0xc5b040af, 0xe57080af, 0xe5b080af, - 0x25034440, 0x254054c4, 0x25034640, 0x25415a05, - 0x25834440, 0x25c54489, 0x250b5d3a, 0x2550dc20, - 0x2518e3e1, 0x2518e021, 0x2518e0a1, 0x2518e121, - 0x2518e1a1, 0x2558e3e2, 0x2558e042, 0x2558e0c2, - 0x2558e142, 0x2598e3e3, 0x2598e063, 0x2598e0e3, - 0x2598e163, 0x25d8e3e4, 0x25d8e084, 0x25d8e104, - 0x25d8e184, 0x2518e407, 0x05214800, 0x05614800, - 0x05a14800, 0x05e14800, 0x05214c00, 0x05614c00, - 0x05a14c00, 0x05e14c00, 0x05304001, 0x05314001, - 0x05a18610, 0x05e18610, 0x05271e11, 0x6545e891, - 0x6585e891, 0x65c5e891, 0x6545c891, 0x6585c891, - 0x65c5c891, 0x45b0c210, 0x45f1c231, 0x1e601000, - 0x1e603000, 0x1e621000, 0x1e623000, 0x1e641000, - 0x1e643000, 0x1e661000, 0x1e663000, 0x1e681000, - 0x1e683000, 0x1e6a1000, 0x1e6a3000, 0x1e6c1000, - 0x1e6c3000, 0x1e6e1000, 0x1e6e3000, 0x1e701000, - 0x1e703000, 0x1e721000, 0x1e723000, 0x1e741000, - 0x1e743000, 0x1e761000, 0x1e763000, 0x1e781000, - 0x1e783000, 0x1e7a1000, 0x1e7a3000, 0x1e7c1000, - 0x1e7c3000, 0x1e7e1000, 0x1e7e3000, 0xf82f8186, - 0xf83001ab, 0xf83713c1, 0xf8332225, 0xf82232d0, - 0xf82d52aa, 0xf83d419b, 0xf83b7023, 0xf83f6278, - 0xf8b18389, 0xf8bb00ef, 0xf8b513f7, 0xf8b923e2, - 0xf8bb3150, 0xf8b75073, 0xf8b04320, 0xf8ba7057, - 0xf8b0608c, 0xf8fc83be, 0xf8f000db, 0xf8e911fd, - 0xf8e720e4, 0xf8ef32e9, 0xf8e85382, 0xf8f540bf, - 0xf8fb7220, 0xf8ef6344, 0xf86882dc, 0xf87b033b, - 0xf8771080, 0xf8662010, 0xf864302f, 0xf86a50a7, - 0xf86a40fc, 0xf87472b7, 0xf866610b, 0xb83180df, - 0xb8310182, 0xb83e107d, 0xb83b23b6, 0xb82e338d, - 0xb83150b8, 0xb822414e, 0xb830736b, 0xb837608c, - 0xb8b68091, 0xb8a10213, 0xb8b011cd, 0xb8ac2222, - 0xb8a332f5, 0xb8a550e6, 0xb8b3438d, 0xb8b170d0, - 0xb8a2607d, 0xb8e481e6, 0xb8f4018d, 0xb8f41328, - 0xb8f42013, 0xb8eb30d8, 0xb8f451df, 0xb8f04006, - 0xb8e7726f, 0xb8fa6149, 0xb87782d5, 0xb87c0062, - 0xb86f1293, 0xb86723a4, 0xb8673120, 0xb87052f4, - 0xb8644150, 0xb877732b, 0xb866621f, 0xce2b06cd, - 0xce14410d, 0xce648df9, 0xce883624, 0xce7c809d, - 0xce7a87b0, 0xcec081c9, 0xce7c8962, 0x2520c143, - 0x25a1d2da, 0x058015ce, 0x05400ed8, 0x0500bb31, - 0x25a0c074, 0x25a1d884, 0x05804944, 0x0540b1d9, - 0x05001548, 0x25a0c49e, 0x2521cabe, 0x058054b3, - 0x0543ab47, 0x050026bb, 0x2560d097, 0x25a1d6fe, - 0x058394b4, 0x0540266d, 0x05003cbc, 0x25a0c1ab, - 0x2561d3f8, 0x05800acd, 0x05403684, 0x05000c07, - 0x2560de64, 0x2521cac5, 0x0583c8b5, 0x05405089, - 0x05003e98, 0x04ad0397, 0x04ac074a, 0x658e023e, - 0x65d50a1d, 0x65820667, 0x0496b13a, 0x04001411, - 0x041a19c2, 0x049095cb, 0x041b0c7d, 0x04d9a876, - 0x049aa27b, 0x04591aa7, 0x04138b25, 0x04119235, - 0x04500a63, 0x0497adc7, 0x04dea9b1, 0x04581e31, - 0x05a78f4f, 0x056494fb, 0x04481f65, 0x048a0f00, - 0x04810074, 0x04dca739, 0x65809031, 0x658d9dae, - 0x65c683d1, 0x658797b6, 0x65828008, 0x04ddb417, - 0x6582baf9, 0x6580b435, 0x65c1b56a, 0x65cdb917, - 0x65c19671, 0x65fe95a4, 0x65f11f3e, 0x65fc298e, - 0x65ada1a5, 0x65b3c967, 0x65e3ec59, 0x65f454a0, - 0x65a86dbc, 0x041b41dd, 0x04587903, 0x042a3321, - 0x04b93281, 0x0470327c, 0x04e131bb, 0x0521692b, - 0x057a6f61, 0x65c887a2, 0x45c2b058, 0x455cb723, - 0x043639a3, 0x045a309b, 0x0498305a, 0x04993ce1, - 0x04483e1e, 0x040a3395, 0x65c72595, 0x6586294b, - 0x65d826c0, 0x04412474, + 0x4eae95ac, 0x0e21cc1f, 0x4e3ecfbc, 0x4e6ccd6a, + 0x2e7c977a, 0x6e649462, 0x2eae95ac, 0x6eb49672, + 0x0ea1cc1f, 0x4ea3cc41, 0x4eefcdcd, 0x2e3fffdd, + 0x6e22fc20, 0x6e75fe93, 0x0e2e65ac, 0x4e336651, + 0x0e7866f6, 0x4e6f65cd, 0x0ebe67bc, 0x4ea067fe, + 0x0e21a41f, 0x4e23a441, 0x0e7ca77a, 0x4e7ea7bc, + 0x0ea6a4a4, 0x4ea0a7fe, 0x0e26f4a4, 0x4e28f4e6, + 0x4e60f7fe, 0x0e3c6f7a, 0x4e346e72, 0x0e6b6d49, + 0x4e6a6d28, 0x0eae6dac, 0x4ea26c20, 0x0e36aeb4, + 0x4e23ac41, 0x0e7aaf38, 0x4e64ac62, 0x0ea2ac20, + 0x4eabad49, 0x0ebaf738, 0x4ebcf77a, 0x4ef2f630, + 0x2ea0effe, 0x6ea5ec83, 0x6eeced6a, 0x0fa710c5, + 0x4f8b8149, 0x4fc710c5, 0x0f8750c5, 0x4faa8128, + 0x4fc750c5, 0x2f8890e6, 0x4fa880e6, 0x6fc59083, + 0x0f6f81cd, 0x4f448862, 0x0f848062, 0x4fab8149, + 0x0e3736d5, 0x4e323630, 0x0e743672, 0x4e6d358b, + 0x0eb736d5, 0x4eb93717, 0x4eee35ac, 0x0e3c3f7a, + 0x4e393f17, 0x0e7e3fbc, 0x4e703dee, 0x0ead3d8b, + 0x4eba3f38, 0x4ee33c41, 0x2e2e8dac, 0x6e218c1f, + 0x2e6c8d6a, 0x6e728e30, 0x2ea98d07, 0x6ea48c62, + 0x6ee58c83, 0x2e2f35cd, 0x6e353693, 0x2e733651, + 0x6e723630, 0x2ea53483, 0x6ea33441, 0x6eed358b, + 0x2e203ffe, 0x6e273cc5, 0x2e6a3d28, 0x6e713e0f, + 0x2ebf3fdd, 0x6ea03ffe, 0x6ee23c20, 0x0e36e6b4, + 0x4e29e507, 0x4e76e6b4, 0x2eb9e717, 0x6ebee7bc, + 0x6ef7e6d5, 0x2e3de79b, 0x6e3be759, 0x6e67e4c5, + 0x65d23ee0, 0x65903d92, 0x65d03fa7, 0x65912fe9, + 0x65d13bf9, 0x65932a0a, 0x25cb90c4, 0x25040bde, + 0x25c11085, 0x25c62c6b, 0x259f2279, 0x259d8993, + 0x24e5102b, 0x24ad5458, 0x24ec7ab5, 0x24387c6d, + 0xba5fd3e3, 0x3a5f03e5, 0xfa411be4, 0x7a42cbe2, + 0x93df03ff, 0xc820ffff, 0x8822fc7f, 0xc8247cbf, + 0x88267fff, 0x4e010fe0, 0x5e040420, 0x4e081fe1, + 0x4e0c1fe1, 0x4e0a1fe1, 0x4e071fe1, 0x4e042c20, + 0x4e062c20, 0x4e052c20, 0x4e083c20, 0x0e0c3c20, + 0x0e0a3c20, 0x0e073c20, 0x9eae0020, 0x0f03f409, + 0x6f03f40e, 0x4cc0ac3f, 0x0ea1b820, 0x4e21c862, + 0x4e61b8a4, 0x05a08020, 0x05104fe0, 0x05505001, + 0x05906fe2, 0x05d03005, 0x05101fea, 0x05901feb, + 0x04b0e3e0, 0x0470e7e1, 0x042f9c20, 0x043f9c35, + 0x047f9c20, 0x04ff9c20, 0x04299420, 0x04319160, + 0x0461943e, 0x04a19020, 0x04038100, 0x040381a0, + 0x040387e1, 0x04438be2, 0x04c38fe3, 0x040181e0, + 0x04018100, 0x04018621, 0x04418b22, 0x04418822, + 0x04818c23, 0x040081e0, 0x04008120, 0x04008761, + 0x04008621, 0x04408822, 0x04808c23, 0x042053ff, + 0x047f5401, 0x25208028, 0x2538cfe0, 0x2578d001, + 0x25b8efe2, 0x25f8f007, 0x2538dfea, 0x25b8dfeb, + 0xa400a3e0, 0xa420a7e0, 0xa4484be0, 0xa467afe0, + 0xa4a8a7ea, 0xa547a814, 0xa4084ffe, 0xa55c53e0, + 0xa5e1540b, 0xe400fbf6, 0xe408ffff, 0xe420e7e0, + 0xe4484be0, 0xe460efe0, 0xe547e400, 0xe4014be0, + 0xe4a84fe0, 0xe5f15000, 0x858043e0, 0x85a043ff, + 0xe59f5d08, 0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, + 0x04e0e3ec, 0x25104042, 0x25104871, 0x25904861, + 0x25904c92, 0x05344020, 0x05744041, 0x05b44062, + 0x05f44083, 0x252c8840, 0x253c1420, 0x25681572, + 0x25a21ce3, 0x25ea1e34, 0x253c0421, 0x25680572, + 0x25a20ce3, 0x25ea0e34, 0x0522c020, 0x05e6c0a4, + 0x2401a001, 0x2443a051, 0x24858881, 0x24c78cd1, + 0x24850891, 0x24c70cc1, 0x250f9001, 0x25508051, + 0x25802491, 0x25df28c1, 0x25850c81, 0x251e10d1, + 0x65816001, 0x65c36051, 0x65854891, 0x65c74cc1, + 0x05733820, 0x05b238a4, 0x05f138e6, 0x0570396a, + 0x65d0a001, 0x65d6a443, 0x65d4a826, 0x6594ac26, + 0x6554ac26, 0x6556ac26, 0x6552ac26, 0x65cbac85, + 0x65caac01, 0x6589ac85, 0x6588ac01, 0x65c9ac85, + 0x65c8ac01, 0x65dea833, 0x659ca509, 0x65d8a801, + 0x65dcac01, 0x655cb241, 0x0520a1e0, 0x0521a601, + 0x052281e0, 0x05238601, 0x04a14026, 0x042244a6, + 0x046344a6, 0x04a444a6, 0x04e544a7, 0x0568aca7, + 0x05b23230, 0x853040af, 0xc5b040af, 0xe57080af, + 0xe5b080af, 0x25034440, 0x254054c4, 0x25034640, + 0x25415a05, 0x25834440, 0x25c54489, 0x250b5d3a, + 0x2550dc20, 0x2518e3e1, 0x2518e021, 0x2518e0a1, + 0x2518e121, 0x2518e1a1, 0x2558e3e2, 0x2558e042, + 0x2558e0c2, 0x2558e142, 0x2598e3e3, 0x2598e063, + 0x2598e0e3, 0x2598e163, 0x25d8e3e4, 0x25d8e084, + 0x25d8e104, 0x25d8e184, 0x2518e407, 0x05214800, + 0x05614800, 0x05a14800, 0x05e14800, 0x05214c00, + 0x05614c00, 0x05a14c00, 0x05e14c00, 0x05304001, + 0x05314001, 0x05a18610, 0x05e18610, 0x05271e11, + 0x6545e891, 0x6585e891, 0x65c5e891, 0x6545c891, + 0x6585c891, 0x65c5c891, 0x45b0c210, 0x45f1c231, + 0x1e601000, 0x1e603000, 0x1e621000, 0x1e623000, + 0x1e641000, 0x1e643000, 0x1e661000, 0x1e663000, + 0x1e681000, 0x1e683000, 0x1e6a1000, 0x1e6a3000, + 0x1e6c1000, 0x1e6c3000, 0x1e6e1000, 0x1e6e3000, + 0x1e701000, 0x1e703000, 0x1e721000, 0x1e723000, + 0x1e741000, 0x1e743000, 0x1e761000, 0x1e763000, + 0x1e781000, 0x1e783000, 0x1e7a1000, 0x1e7a3000, + 0x1e7c1000, 0x1e7c3000, 0x1e7e1000, 0x1e7e3000, + 0xf8338131, 0xf83c01fb, 0xf82712f5, 0xf83f2059, + 0xf83f31fb, 0xf82a5277, 0xf8234010, 0xf83972fa, + 0xf8226190, 0xf8a483dc, 0xf8bd0370, 0xf8a613a9, + 0xf8b02087, 0xf8a7312f, 0xf8b75048, 0xf8bc43f5, + 0xf8a5701b, 0xf8b1608f, 0xf8fa8388, 0xf8f6037b, + 0xf8f91017, 0xf8e421e6, 0xf8e031e4, 0xf8e150ea, + 0xf8e5438a, 0xf8e772f4, 0xf8f56166, 0xf86883f1, + 0xf8660051, 0xf86c13be, 0xf86322db, 0xf87d31ae, + 0xf87c5311, 0xf86541c2, 0xf86a7170, 0xf87b6197, + 0xb8248236, 0xb8240261, 0xb83011b0, 0xb82e204c, + 0xb83132a3, 0xb83750c5, 0xb82741b3, 0xb83c7211, + 0xb82663a2, 0xb8a380c4, 0xb8b001b4, 0xb8ac1114, + 0xb8b92274, 0xb8a0330b, 0xb8a653f4, 0xb8ae40d0, + 0xb8a071e7, 0xb8b3613a, 0xb8ea82b7, 0xb8f6005c, + 0xb8e3126f, 0xb8f42087, 0xb8fd3007, 0xb8e95290, + 0xb8f74204, 0xb8ea7177, 0xb8f963e6, 0xb87082ed, + 0xb86c01c1, 0xb8691215, 0xb87a208f, 0xb8643110, + 0xb866509e, 0xb87d43b1, 0xb87a71e9, 0xb86263ab, + 0xce216ce3, 0xce0e2255, 0xce798ed2, 0xce959685, + 0xce7e8217, 0xce608694, 0xcec08264, 0xce748898, + 0x25e0da44, 0x2521c8f3, 0x05801548, 0x0540cbdf, + 0x05006521, 0x2560c7a0, 0x25a1c498, 0x058026bb, + 0x05407dd8, 0x0500f3d6, 0x2560ce3d, 0x2521d4b4, + 0x05803cbc, 0x05404d6c, 0x05001b89, 0x25a0c532, + 0x2521cc40, 0x05800c08, 0x054074c4, 0x050034a0, + 0x2520c9e3, 0x25e1ca93, 0x05803e98, 0x05425238, + 0x050024cb, 0x25a0ce7f, 0x25e1d0c3, 0x05802676, + 0x05401e63, 0x05002d49, 0x04e20080, 0x04ab04ce, + 0x659e022e, 0x65970863, 0x659c0703, 0x04d6b4f3, + 0x04400cb5, 0x049a06da, 0x04508071, 0x045b0d14, + 0x0459b22e, 0x04daba4d, 0x04590a13, 0x0493979b, + 0x04d188a8, 0x0450081c, 0x0417b6b9, 0x041eb743, + 0x04981e7a, 0x05e78dc1, 0x0564824e, 0x048816ff, + 0x040a0d1e, 0x04810ee0, 0x04dcb340, 0x65c08ed8, + 0x65cd8162, 0x65c6970c, 0x65c79e29, 0x65c29494, + 0x04ddbecd, 0x65c2ba5f, 0x65c0a9af, 0x6581a434, + 0x658da0ee, 0x65c1908c, 0x65be806f, 0x65ff0694, + 0x65ee2d2d, 0x65a3af81, 0x65a9cb3a, 0x65e1e9da, + 0x65f447ba, 0x65e17da6, 0x0401482b, 0x040279fb, + 0x0439323e, 0x04a33302, 0x046331bd, 0x04fc320e, + 0x05bb6964, 0x05e16e02, 0x65c897e7, 0x4596b150, + 0x4516b4fd, 0x0438396c, 0x041a280b, 0x04183697, + 0x04192de3, 0x04083b7e, 0x04ca3955, 0x65873883, + 0x658622a6, 0x65d83bd9, 0x0441303f, 0x0e2e11ac, + 0x4e2013fe, 0x0e6f11cd, 0x4e6a1128, 0x0ebb1359, + 0x4ebf13dd, 0x2e231041, 0x6e21101f, 0x2e791317, + 0x6e61101f, 0x2eb612b4, 0x6ea21020, }; // END Generated code -- do not edit From 1cf26a5179e619f17909426fdb26a3fb3b748483 Mon Sep 17 00:00:00 2001 From: Oli Gillespie Date: Mon, 30 Sep 2024 10:53:20 +0000 Subject: [PATCH 09/15] 8341013: Optimize x86/aarch64 MD5 intrinsics by reducing data dependency Reviewed-by: mli, ascarpino --- src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp | 10 +++++----- src/hotspot/cpu/x86/macroAssembler_x86_md5.cpp | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index ac88b427459c0..3dbde1ae8242b 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -3419,15 +3419,15 @@ class StubGenerator: public StubCodeGenerator { Register rscratch3 = r10; Register rscratch4 = r11; - __ andw(rscratch3, r2, r4); - __ bicw(rscratch4, r3, r4); reg_cache.extract_u32(rscratch1, k); __ movw(rscratch2, t); - __ orrw(rscratch3, rscratch3, rscratch4); __ addw(rscratch4, r1, rscratch2); __ addw(rscratch4, rscratch4, rscratch1); - __ addw(rscratch3, rscratch3, rscratch4); - __ rorw(rscratch2, rscratch3, 32 - s); + __ bicw(rscratch2, r3, r4); + __ andw(rscratch3, r2, r4); + __ addw(rscratch2, rscratch2, rscratch4); + __ addw(rscratch2, rscratch2, rscratch3); + __ rorw(rscratch2, rscratch2, 32 - s); __ addw(r1, rscratch2, r2); } diff --git a/src/hotspot/cpu/x86/macroAssembler_x86_md5.cpp b/src/hotspot/cpu/x86/macroAssembler_x86_md5.cpp index 439c17b10d37a..09d379a4296d4 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86_md5.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86_md5.cpp @@ -81,8 +81,8 @@ void MacroAssembler::fast_md5(Register buf, Address state, Address ofs, Address notl(rsi); \ andl(rdi, r2); \ andl(rsi, r3); \ - orl(rsi, rdi); \ addl(r1, rsi); \ + addl(r1, rdi); \ roll(r1, s); \ addl(r1, r2); From 58b6fc5baa0931fa6f2aa37bf0bb125497cf6cc9 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Mon, 30 Sep 2024 10:56:52 +0000 Subject: [PATCH 10/15] 8341197: [BACKOUT] 8322770: Implement C2 VectorizedHashCode on AArch64 Reviewed-by: shade, jpai --- src/hotspot/cpu/aarch64/aarch64.ad | 78 -- src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 68 +- .../cpu/aarch64/c2_MacroAssembler_aarch64.cpp | 91 -- .../cpu/aarch64/c2_MacroAssembler_aarch64.hpp | 3 - .../cpu/aarch64/stubGenerator_aarch64.cpp | 312 ----- .../cpu/aarch64/stubRoutines_aarch64.cpp | 7 +- .../cpu/aarch64/stubRoutines_aarch64.hpp | 26 +- .../cpu/aarch64/vm_version_aarch64.cpp | 4 - src/hotspot/share/utilities/intpow.hpp | 46 - test/hotspot/gtest/aarch64/aarch64-asmtest.py | 111 -- test/hotspot/gtest/aarch64/asmtest.out.h | 1189 ++++++++--------- 11 files changed, 580 insertions(+), 1355 deletions(-) delete mode 100644 src/hotspot/share/utilities/intpow.hpp diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 0a93c27c2686b..39eae43a287e7 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -4931,60 +4931,6 @@ operand vRegD_V7() interface(REG_INTER); %} -operand vRegD_V12() -%{ - constraint(ALLOC_IN_RC(v12_reg)); - match(RegD); - op_cost(0); - format %{ %} - interface(REG_INTER); -%} - -operand vRegD_V13() -%{ - constraint(ALLOC_IN_RC(v13_reg)); - match(RegD); - op_cost(0); - format %{ %} - interface(REG_INTER); -%} - -operand vRegD_V14() -%{ - constraint(ALLOC_IN_RC(v14_reg)); - match(RegD); - op_cost(0); - format %{ %} - interface(REG_INTER); -%} - -operand vRegD_V15() -%{ - constraint(ALLOC_IN_RC(v15_reg)); - match(RegD); - op_cost(0); - format %{ %} - interface(REG_INTER); -%} - -operand vRegD_V16() -%{ - constraint(ALLOC_IN_RC(v16_reg)); - match(RegD); - op_cost(0); - format %{ %} - interface(REG_INTER); -%} - -operand vRegD_V17() -%{ - constraint(ALLOC_IN_RC(v17_reg)); - match(RegD); - op_cost(0); - format %{ %} - interface(REG_INTER); -%} - operand pReg() %{ constraint(ALLOC_IN_RC(pr_reg)); @@ -16605,30 +16551,6 @@ instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, ins_pipe(pipe_class_memory); %} -instruct arrays_hashcode(iRegP_R1 ary, iRegI_R2 cnt, iRegI_R0 result, immI basic_type, - vRegD_V0 vtmp0, vRegD_V1 vtmp1, vRegD_V2 vtmp2, vRegD_V3 vtmp3, - vRegD_V4 vtmp4, vRegD_V5 vtmp5, vRegD_V6 vtmp6, vRegD_V7 vtmp7, - vRegD_V12 vtmp8, vRegD_V13 vtmp9, vRegD_V14 vtmp10, - vRegD_V15 vtmp11, vRegD_V16 vtmp12, vRegD_V17 vtmp13, - rFlagsReg cr) -%{ - match(Set result (VectorizedHashCode (Binary ary cnt) (Binary result basic_type))); - effect(TEMP vtmp0, TEMP vtmp1, TEMP vtmp2, TEMP vtmp3, TEMP vtmp4, TEMP vtmp5, TEMP vtmp6, - TEMP vtmp7, TEMP vtmp8, TEMP vtmp9, TEMP vtmp10, TEMP vtmp11, TEMP vtmp12, TEMP vtmp13, - USE_KILL ary, USE_KILL cnt, USE basic_type, KILL cr); - - format %{ "Array HashCode array[] $ary,$cnt,$result,$basic_type -> $result // KILL all" %} - ins_encode %{ - address tpc = __ arrays_hashcode($ary$$Register, $cnt$$Register, $result$$Register, - (BasicType)$basic_type$$constant); - if (tpc == nullptr) { - ciEnv::current()->record_failure("CodeCache is full"); - return; - } - %} - ins_pipe(pipe_class_memory); -%} - instruct count_positives(iRegP_R1 ary1, iRegI_R2 len, iRegI_R0 result, rFlagsReg cr) %{ match(Set result (CountPositives ary1 len)); diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index a5e0e2665af92..28a0cc2c7d940 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2024, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -287,11 +287,6 @@ class Instruction_aarch64 { f(r->raw_encoding(), lsb + 4, lsb); } - //<0-15>reg: As `rf(FloatRegister)`, but only the lower 16 FloatRegisters are allowed. - void lrf(FloatRegister r, int lsb) { - f(r->raw_encoding(), lsb + 3, lsb); - } - void prf(PRegister r, int lsb) { f(r->raw_encoding(), lsb + 3, lsb); } @@ -770,7 +765,6 @@ class Assembler : public AbstractAssembler { #define f current_insn.f #define sf current_insn.sf #define rf current_insn.rf -#define lrf current_insn.lrf #define srf current_insn.srf #define zrf current_insn.zrf #define prf current_insn.prf @@ -1596,16 +1590,6 @@ class Assembler : public AbstractAssembler { #undef INSN - // Load/store a register, but with a BasicType parameter. Loaded signed integer values are - // extended to 64 bits. - void load(Register Rt, const Address &adr, BasicType bt) { - int op = (is_signed_subword_type(bt) || bt == T_INT) ? 0b10 : 0b01; - ld_st2(Rt, adr, exact_log2(type2aelembytes(bt)), op); - } - void store(Register Rt, const Address &adr, BasicType bt) { - ld_st2(Rt, adr, exact_log2(type2aelembytes(bt)), 0b00); - } - /* SIMD extensions * * We just use FloatRegister in the following. They are exactly the same @@ -2603,7 +2587,6 @@ template INSN(addpv, 0, 0b101111, true); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S, T2D INSN(smullv, 0, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(umullv, 1, 0b110000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S - INSN(smlalv, 0, 0b100000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(umlalv, 1, 0b100000, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(maxv, 0, 0b011001, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S INSN(minv, 0, 0b011011, false); // accepted arrangements: T8B, T16B, T4H, T8H, T2S, T4S @@ -2877,28 +2860,6 @@ template // FMULX - Vector - Scalar INSN(fmulxvs, 1, 0b1001); -#undef INSN - -#define INSN(NAME, op1, op2) \ - void NAME(FloatRegister Vd, SIMD_Arrangement T, FloatRegister Vn, FloatRegister Vm, int index) { \ - starti; \ - assert(T == T4H || T == T8H || T == T2S || T == T4S, "invalid arrangement"); \ - assert(index >= 0 && \ - ((T == T2S && index <= 1) || (T != T2S && index <= 3) || (T == T8H && index <= 7)), \ - "invalid index"); \ - assert((T != T4H && T != T8H) || Vm->encoding() < 16, "invalid source SIMD&FP register"); \ - f(0, 31), f((int)T & 1, 30), f(op1, 29), f(0b01111, 28, 24); \ - if (T == T4H || T == T8H) { \ - f(0b01, 23, 22), f(index & 0b11, 21, 20), lrf(Vm, 16), f(index >> 2 & 1, 11); \ - } else { \ - f(0b10, 23, 22), f(index & 1, 21), rf(Vm, 16), f(index >> 1, 11); \ - } \ - f(op2, 15, 12), f(0, 10), rf(Vn, 5), rf(Vd, 0); \ - } - - // MUL - Vector - Scalar - INSN(mulvs, 0, 0b1000); - #undef INSN // Floating-point Reciprocal Estimate @@ -3062,33 +3023,6 @@ template umov(Xd, Vn, T, index); } - protected: - void _xaddwv(bool is_unsigned, FloatRegister Vd, FloatRegister Vn, SIMD_Arrangement Ta, - FloatRegister Vm, SIMD_Arrangement Tb) { - starti; - assert((Tb >> 1) + 1 == (Ta >> 1), "Incompatible arrangement"); - f(0, 31), f((int)Tb & 1, 30), f(is_unsigned ? 1 : 0, 29), f(0b01110, 28, 24); - f((int)(Ta >> 1) - 1, 23, 22), f(1, 21), rf(Vm, 16), f(0b000100, 15, 10), rf(Vn, 5), rf(Vd, 0); - } - - public: -#define INSN(NAME, assertion, is_unsigned) \ - void NAME(FloatRegister Vd, FloatRegister Vn, SIMD_Arrangement Ta, FloatRegister Vm, \ - SIMD_Arrangement Tb) { \ - assert((assertion), "invalid arrangement"); \ - _xaddwv(is_unsigned, Vd, Vn, Ta, Vm, Tb); \ - } - -public: - - INSN(uaddwv, Tb == T8B || Tb == T4H || Tb == T2S, /*is_unsigned*/true) - INSN(uaddwv2, Tb == T16B || Tb == T8H || Tb == T4S, /*is_unsigned*/true) - INSN(saddwv, Tb == T8B || Tb == T4H || Tb == T2S, /*is_unsigned*/false) - INSN(saddwv2, Tb == T16B || Tb == T8H || Tb == T4S, /*is_unsigned*/false) - -#undef INSN - - private: void _pmull(FloatRegister Vd, SIMD_Arrangement Ta, FloatRegister Vn, FloatRegister Vm, SIMD_Arrangement Tb) { starti; diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index ab2bd7d782c04..b4c12ecd4a849 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -33,7 +33,6 @@ #include "opto/subnode.hpp" #include "runtime/stubRoutines.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/powerOfTwo.hpp" #ifdef PRODUCT #define BLOCK_COMMENT(str) /* nothing */ @@ -47,96 +46,6 @@ typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr); -// jdk.internal.util.ArraysSupport.vectorizedHashCode -address C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register result, - BasicType eltype) { - assert_different_registers(ary, cnt, result, rscratch1, rscratch2); - - Register tmp1 = rscratch1, tmp2 = rscratch2; - - Label TAIL, STUB_SWITCH, STUB_SWITCH_OUT, LOOP, BR_BASE, LARGE, DONE; - - // Vectorization factor. Number of array elements loaded to one SIMD&FP registers by the stubs. We - // use 8H load arrangements for chars and shorts and 8B for booleans and bytes. It's possible to - // use 4H for chars and shorts instead, but using 8H gives better performance. - const size_t vf = eltype == T_BOOLEAN || eltype == T_BYTE ? 8 - : eltype == T_CHAR || eltype == T_SHORT ? 8 - : eltype == T_INT ? 4 - : 0; - guarantee(vf, "unsupported eltype"); - - // Unroll factor for the scalar loop below. The value is chosen based on performance analysis. - const size_t unroll_factor = 4; - - switch (eltype) { - case T_BOOLEAN: - BLOCK_COMMENT("arrays_hashcode(unsigned byte) {"); - break; - case T_CHAR: - BLOCK_COMMENT("arrays_hashcode(char) {"); - break; - case T_BYTE: - BLOCK_COMMENT("arrays_hashcode(byte) {"); - break; - case T_SHORT: - BLOCK_COMMENT("arrays_hashcode(short) {"); - break; - case T_INT: - BLOCK_COMMENT("arrays_hashcode(int) {"); - break; - default: - ShouldNotReachHere(); - } - - // large_arrays_hashcode(T_INT) performs worse than the scalar loop below when the Neon loop - // implemented by the stub executes just once. Call the stub only if at least two iterations will - // be executed. - const size_t large_threshold = eltype == T_INT ? vf * 2 : vf; - cmpw(cnt, large_threshold); - br(Assembler::HS, LARGE); - - bind(TAIL); - - // The andr performs cnt % uf where uf = unroll_factor. The subtract shifted by 3 offsets past - // uf - (cnt % uf) pairs of load + madd insns i.e. it only executes cnt % uf load + madd pairs. - // Iteration eats up the remainder, uf elements at a time. - assert(is_power_of_2(unroll_factor), "can't use this value to calculate the jump target PC"); - andr(tmp2, cnt, unroll_factor - 1); - adr(tmp1, BR_BASE); - sub(tmp1, tmp1, tmp2, ext::sxtw, 3); - movw(tmp2, 0x1f); - br(tmp1); - - bind(LOOP); - for (size_t i = 0; i < unroll_factor; ++i) { - load(tmp1, Address(post(ary, type2aelembytes(eltype))), eltype); - maddw(result, result, tmp2, tmp1); - } - bind(BR_BASE); - subsw(cnt, cnt, unroll_factor); - br(Assembler::HS, LOOP); - - b(DONE); - - bind(LARGE); - - RuntimeAddress stub = RuntimeAddress(StubRoutines::aarch64::large_arrays_hashcode(eltype)); - assert(stub.target() != nullptr, "array_hashcode stub has not been generated"); - address tpc = trampoline_call(stub); - if (tpc == nullptr) { - DEBUG_ONLY(reset_labels(TAIL, BR_BASE)); - postcond(pc() == badAddress); - return nullptr; - } - - bind(DONE); - - BLOCK_COMMENT("} // arrays_hashcode"); - - postcond(pc() != badAddress); - return pc(); -} - void C2_MacroAssembler::fast_lock(Register objectReg, Register boxReg, Register tmpReg, Register tmp2Reg, Register tmp3Reg) { Register oop = objectReg; diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp index 28cc401a1b2c8..43e60ae5a48f8 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp @@ -35,9 +35,6 @@ enum shift_kind kind = Assembler::LSL, unsigned shift = 0); public: - // jdk.internal.util.ArraysSupport.vectorizedHashCode - address arrays_hashcode(Register ary, Register cnt, Register result, BasicType eltype); - // Code used by cmpFastLock and cmpFastUnlock mach instructions in .ad file. void fast_lock(Register object, Register box, Register tmp, Register tmp2, Register tmp3); void fast_unlock(Register object, Register box, Register tmp, Register tmp2); diff --git a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp index 3dbde1ae8242b..eb235f8472c1d 100644 --- a/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubGenerator_aarch64.cpp @@ -53,9 +53,7 @@ #include "runtime/stubRoutines.hpp" #include "utilities/align.hpp" #include "utilities/checkedCast.hpp" -#include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" -#include "utilities/intpow.hpp" #include "utilities/powerOfTwo.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" @@ -5313,309 +5311,6 @@ class StubGenerator: public StubCodeGenerator { return entry; } - // result = r0 - return value. Contains initial hashcode value on entry. - // ary = r1 - array address - // cnt = r2 - elements count - // Clobbers: v0-v13, rscratch1, rscratch2 - address generate_large_arrays_hashcode(BasicType eltype) { - const Register result = r0, ary = r1, cnt = r2; - const FloatRegister vdata0 = v3, vdata1 = v2, vdata2 = v1, vdata3 = v0; - const FloatRegister vmul0 = v4, vmul1 = v5, vmul2 = v6, vmul3 = v7; - const FloatRegister vpow = v8; // powers of 31: <31^3, ..., 31^0> - const FloatRegister vpowm = v9; - - assert_different_registers(ary, cnt, result); - assert_different_registers(vdata0, vdata1, vdata2, vdata3, vmul0, vmul1, vmul2, vmul3, vpow, - vpowm); - - Label SMALL_LOOP, LARGE_LOOP_PREHEADER, LARGE_LOOP, TAIL, TAIL_SHORTCUT, BR_BASE; - - unsigned int vf; // vectorization factor - bool multiply_by_halves; - Assembler::SIMD_Arrangement load_arrangement; - switch (eltype) { - case T_BOOLEAN: - case T_BYTE: - load_arrangement = Assembler::T8B; - multiply_by_halves = true; - vf = 8; - break; - case T_CHAR: - case T_SHORT: - load_arrangement = Assembler::T8H; - multiply_by_halves = true; - vf = 8; - break; - case T_INT: - load_arrangement = Assembler::T4S; - multiply_by_halves = false; - vf = 4; - break; - default: - ShouldNotReachHere(); - } - - // Unroll factor - const unsigned uf = 4; - - // Effective vectorization factor - const unsigned evf = vf * uf; - - __ align(CodeEntryAlignment); - - const char *mark_name = ""; - switch (eltype) { - case T_BOOLEAN: - mark_name = "_large_arrays_hashcode_boolean"; - break; - case T_BYTE: - mark_name = "_large_arrays_hashcode_byte"; - break; - case T_CHAR: - mark_name = "_large_arrays_hashcode_char"; - break; - case T_SHORT: - mark_name = "_large_arrays_hashcode_short"; - break; - case T_INT: - mark_name = "_large_arrays_hashcode_int"; - break; - default: - mark_name = "_large_arrays_hashcode_incorrect_type"; - __ should_not_reach_here(); - }; - - StubCodeMark mark(this, "StubRoutines", mark_name); - - address entry = __ pc(); - __ enter(); - - // Put 0-3'th powers of 31 into a single SIMD register together. The register will be used in - // the SMALL and LARGE LOOPS' epilogues. The initialization is hoisted here and the register's - // value shouldn't change throughout both loops. - __ movw(rscratch1, intpow(31U, 3)); - __ mov(vpow, Assembler::S, 0, rscratch1); - __ movw(rscratch1, intpow(31U, 2)); - __ mov(vpow, Assembler::S, 1, rscratch1); - __ movw(rscratch1, intpow(31U, 1)); - __ mov(vpow, Assembler::S, 2, rscratch1); - __ movw(rscratch1, intpow(31U, 0)); - __ mov(vpow, Assembler::S, 3, rscratch1); - - __ mov(vmul0, Assembler::T16B, 0); - __ mov(vmul0, Assembler::S, 3, result); - - __ andr(rscratch2, cnt, (uf - 1) * vf); - __ cbz(rscratch2, LARGE_LOOP_PREHEADER); - - __ movw(rscratch1, intpow(31U, multiply_by_halves ? vf / 2 : vf)); - __ mov(vpowm, Assembler::S, 0, rscratch1); - - // SMALL LOOP - __ bind(SMALL_LOOP); - - __ ld1(vdata0, load_arrangement, Address(__ post(ary, vf * type2aelembytes(eltype)))); - __ mulvs(vmul0, Assembler::T4S, vmul0, vpowm, 0); - __ subsw(rscratch2, rscratch2, vf); - - if (load_arrangement == Assembler::T8B) { - // Extend 8B to 8H to be able to use vector multiply - // instructions - assert(load_arrangement == Assembler::T8B, "expected to extend 8B to 8H"); - if (is_signed_subword_type(eltype)) { - __ sxtl(vdata0, Assembler::T8H, vdata0, load_arrangement); - } else { - __ uxtl(vdata0, Assembler::T8H, vdata0, load_arrangement); - } - } - - switch (load_arrangement) { - case Assembler::T4S: - __ addv(vmul0, load_arrangement, vmul0, vdata0); - break; - case Assembler::T8B: - case Assembler::T8H: - assert(is_subword_type(eltype), "subword type expected"); - if (is_signed_subword_type(eltype)) { - __ saddwv(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T4H); - } else { - __ uaddwv(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T4H); - } - break; - default: - __ should_not_reach_here(); - } - - // Process the upper half of a vector - if (load_arrangement == Assembler::T8B || load_arrangement == Assembler::T8H) { - __ mulvs(vmul0, Assembler::T4S, vmul0, vpowm, 0); - if (is_signed_subword_type(eltype)) { - __ saddwv2(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T8H); - } else { - __ uaddwv2(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T8H); - } - } - - __ br(Assembler::HI, SMALL_LOOP); - - // SMALL LOOP'S EPILOQUE - __ lsr(rscratch2, cnt, exact_log2(evf)); - __ cbnz(rscratch2, LARGE_LOOP_PREHEADER); - - __ mulv(vmul0, Assembler::T4S, vmul0, vpow); - __ addv(vmul0, Assembler::T4S, vmul0); - __ umov(result, vmul0, Assembler::S, 0); - - // TAIL - __ bind(TAIL); - - // The andr performs cnt % vf. The subtract shifted by 3 offsets past vf - 1 - (cnt % vf) pairs - // of load + madd insns i.e. it only executes cnt % vf load + madd pairs. - assert(is_power_of_2(vf), "can't use this value to calculate the jump target PC"); - __ andr(rscratch2, cnt, vf - 1); - __ bind(TAIL_SHORTCUT); - __ adr(rscratch1, BR_BASE); - __ sub(rscratch1, rscratch1, rscratch2, ext::uxtw, 3); - __ movw(rscratch2, 0x1f); - __ br(rscratch1); - - for (size_t i = 0; i < vf - 1; ++i) { - __ load(rscratch1, Address(__ post(ary, type2aelembytes(eltype))), - eltype); - __ maddw(result, result, rscratch2, rscratch1); - } - __ bind(BR_BASE); - - __ leave(); - __ ret(lr); - - // LARGE LOOP - __ bind(LARGE_LOOP_PREHEADER); - - __ lsr(rscratch2, cnt, exact_log2(evf)); - - if (multiply_by_halves) { - // 31^4 - multiplier between lower and upper parts of a register - __ movw(rscratch1, intpow(31U, vf / 2)); - __ mov(vpowm, Assembler::S, 1, rscratch1); - // 31^28 - remainder of the iteraion multiplier, 28 = 32 - 4 - __ movw(rscratch1, intpow(31U, evf - vf / 2)); - __ mov(vpowm, Assembler::S, 0, rscratch1); - } else { - // 31^16 - __ movw(rscratch1, intpow(31U, evf)); - __ mov(vpowm, Assembler::S, 0, rscratch1); - } - - __ mov(vmul3, Assembler::T16B, 0); - __ mov(vmul2, Assembler::T16B, 0); - __ mov(vmul1, Assembler::T16B, 0); - - __ bind(LARGE_LOOP); - - __ mulvs(vmul3, Assembler::T4S, vmul3, vpowm, 0); - __ mulvs(vmul2, Assembler::T4S, vmul2, vpowm, 0); - __ mulvs(vmul1, Assembler::T4S, vmul1, vpowm, 0); - __ mulvs(vmul0, Assembler::T4S, vmul0, vpowm, 0); - - __ ld1(vdata3, vdata2, vdata1, vdata0, load_arrangement, - Address(__ post(ary, evf * type2aelembytes(eltype)))); - - if (load_arrangement == Assembler::T8B) { - // Extend 8B to 8H to be able to use vector multiply - // instructions - assert(load_arrangement == Assembler::T8B, "expected to extend 8B to 8H"); - if (is_signed_subword_type(eltype)) { - __ sxtl(vdata3, Assembler::T8H, vdata3, load_arrangement); - __ sxtl(vdata2, Assembler::T8H, vdata2, load_arrangement); - __ sxtl(vdata1, Assembler::T8H, vdata1, load_arrangement); - __ sxtl(vdata0, Assembler::T8H, vdata0, load_arrangement); - } else { - __ uxtl(vdata3, Assembler::T8H, vdata3, load_arrangement); - __ uxtl(vdata2, Assembler::T8H, vdata2, load_arrangement); - __ uxtl(vdata1, Assembler::T8H, vdata1, load_arrangement); - __ uxtl(vdata0, Assembler::T8H, vdata0, load_arrangement); - } - } - - switch (load_arrangement) { - case Assembler::T4S: - __ addv(vmul3, load_arrangement, vmul3, vdata3); - __ addv(vmul2, load_arrangement, vmul2, vdata2); - __ addv(vmul1, load_arrangement, vmul1, vdata1); - __ addv(vmul0, load_arrangement, vmul0, vdata0); - break; - case Assembler::T8B: - case Assembler::T8H: - assert(is_subword_type(eltype), "subword type expected"); - if (is_signed_subword_type(eltype)) { - __ saddwv(vmul3, vmul3, Assembler::T4S, vdata3, Assembler::T4H); - __ saddwv(vmul2, vmul2, Assembler::T4S, vdata2, Assembler::T4H); - __ saddwv(vmul1, vmul1, Assembler::T4S, vdata1, Assembler::T4H); - __ saddwv(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T4H); - } else { - __ uaddwv(vmul3, vmul3, Assembler::T4S, vdata3, Assembler::T4H); - __ uaddwv(vmul2, vmul2, Assembler::T4S, vdata2, Assembler::T4H); - __ uaddwv(vmul1, vmul1, Assembler::T4S, vdata1, Assembler::T4H); - __ uaddwv(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T4H); - } - break; - default: - __ should_not_reach_here(); - } - - // Process the upper half of a vector - if (load_arrangement == Assembler::T8B || load_arrangement == Assembler::T8H) { - __ mulvs(vmul3, Assembler::T4S, vmul3, vpowm, 1); - __ mulvs(vmul2, Assembler::T4S, vmul2, vpowm, 1); - __ mulvs(vmul1, Assembler::T4S, vmul1, vpowm, 1); - __ mulvs(vmul0, Assembler::T4S, vmul0, vpowm, 1); - if (is_signed_subword_type(eltype)) { - __ saddwv2(vmul3, vmul3, Assembler::T4S, vdata3, Assembler::T8H); - __ saddwv2(vmul2, vmul2, Assembler::T4S, vdata2, Assembler::T8H); - __ saddwv2(vmul1, vmul1, Assembler::T4S, vdata1, Assembler::T8H); - __ saddwv2(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T8H); - } else { - __ uaddwv2(vmul3, vmul3, Assembler::T4S, vdata3, Assembler::T8H); - __ uaddwv2(vmul2, vmul2, Assembler::T4S, vdata2, Assembler::T8H); - __ uaddwv2(vmul1, vmul1, Assembler::T4S, vdata1, Assembler::T8H); - __ uaddwv2(vmul0, vmul0, Assembler::T4S, vdata0, Assembler::T8H); - } - } - - __ subsw(rscratch2, rscratch2, 1); - __ br(Assembler::HI, LARGE_LOOP); - - __ mulv(vmul3, Assembler::T4S, vmul3, vpow); - __ addv(vmul3, Assembler::T4S, vmul3); - __ umov(result, vmul3, Assembler::S, 0); - - __ mov(rscratch2, intpow(31U, vf)); - - __ mulv(vmul2, Assembler::T4S, vmul2, vpow); - __ addv(vmul2, Assembler::T4S, vmul2); - __ umov(rscratch1, vmul2, Assembler::S, 0); - __ maddw(result, result, rscratch2, rscratch1); - - __ mulv(vmul1, Assembler::T4S, vmul1, vpow); - __ addv(vmul1, Assembler::T4S, vmul1); - __ umov(rscratch1, vmul1, Assembler::S, 0); - __ maddw(result, result, rscratch2, rscratch1); - - __ mulv(vmul0, Assembler::T4S, vmul0, vpow); - __ addv(vmul0, Assembler::T4S, vmul0); - __ umov(rscratch1, vmul0, Assembler::S, 0); - __ maddw(result, result, rscratch2, rscratch1); - - __ andr(rscratch2, cnt, vf - 1); - __ cbnz(rscratch2, TAIL_SHORTCUT); - - __ leave(); - __ ret(lr); - - return entry; - } - address generate_dsin_dcos(bool isCos) { __ align(CodeEntryAlignment); StubCodeMark mark(this, "StubRoutines", isCos ? "libmDcos" : "libmDsin"); @@ -8562,13 +8257,6 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::aarch64::_large_array_equals = generate_large_array_equals(); } - // arrays_hascode stub for large arrays. - StubRoutines::aarch64::_large_arrays_hashcode_boolean = generate_large_arrays_hashcode(T_BOOLEAN); - StubRoutines::aarch64::_large_arrays_hashcode_byte = generate_large_arrays_hashcode(T_BYTE); - StubRoutines::aarch64::_large_arrays_hashcode_char = generate_large_arrays_hashcode(T_CHAR); - StubRoutines::aarch64::_large_arrays_hashcode_int = generate_large_arrays_hashcode(T_INT); - StubRoutines::aarch64::_large_arrays_hashcode_short = generate_large_arrays_hashcode(T_SHORT); - // byte_array_inflate stub for large arrays. StubRoutines::aarch64::_large_byte_array_inflate = generate_large_byte_array_inflate(); diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp index dee615df5a51f..80875a3b3cdcf 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, 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. * @@ -48,11 +48,6 @@ address StubRoutines::aarch64::_zero_blocks = nullptr; address StubRoutines::aarch64::_count_positives = nullptr; address StubRoutines::aarch64::_count_positives_long = nullptr; address StubRoutines::aarch64::_large_array_equals = nullptr; -address StubRoutines::aarch64::_large_arrays_hashcode_boolean = nullptr; -address StubRoutines::aarch64::_large_arrays_hashcode_byte = nullptr; -address StubRoutines::aarch64::_large_arrays_hashcode_char = nullptr; -address StubRoutines::aarch64::_large_arrays_hashcode_int = nullptr; -address StubRoutines::aarch64::_large_arrays_hashcode_short = nullptr; address StubRoutines::aarch64::_compare_long_string_LL = nullptr; address StubRoutines::aarch64::_compare_long_string_UU = nullptr; address StubRoutines::aarch64::_compare_long_string_LU = nullptr; diff --git a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp index 7d3b72a88363d..e6438908ce4c6 100644 --- a/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/stubRoutines_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, 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. * @@ -62,11 +62,6 @@ class aarch64 { static address _zero_blocks; static address _large_array_equals; - static address _large_arrays_hashcode_boolean; - static address _large_arrays_hashcode_byte; - static address _large_arrays_hashcode_char; - static address _large_arrays_hashcode_int; - static address _large_arrays_hashcode_short; static address _compare_long_string_LL; static address _compare_long_string_LU; static address _compare_long_string_UL; @@ -150,25 +145,6 @@ class aarch64 { return _large_array_equals; } - static address large_arrays_hashcode(BasicType eltype) { - switch (eltype) { - case T_BOOLEAN: - return _large_arrays_hashcode_boolean; - case T_BYTE: - return _large_arrays_hashcode_byte; - case T_CHAR: - return _large_arrays_hashcode_char; - case T_SHORT: - return _large_arrays_hashcode_short; - case T_INT: - return _large_arrays_hashcode_int; - default: - ShouldNotReachHere(); - } - - return nullptr; - } - static address compare_long_string_LL() { return _compare_long_string_LL; } diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 81e39113afaab..d71162ac568ea 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -574,10 +574,6 @@ void VM_Version::initialize() { if (FLAG_IS_DEFAULT(UsePoly1305Intrinsics)) { FLAG_SET_DEFAULT(UsePoly1305Intrinsics, true); } - - if (FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) { - FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, true); - } #endif _spin_wait = get_spin_wait_desc(); diff --git a/src/hotspot/share/utilities/intpow.hpp b/src/hotspot/share/utilities/intpow.hpp deleted file mode 100644 index 0b441a55c4c96..0000000000000 --- a/src/hotspot/share/utilities/intpow.hpp +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2024, 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. - * - */ - -#ifndef SHARE_UTILITIES_INTPOW_HPP -#define SHARE_UTILITIES_INTPOW_HPP - -#include "metaprogramming/enableIf.hpp" -#include -#include - -// Raise v to the power p mod 2**N, where N is the width of the type T. -template ::value && std::is_unsigned::value)> -static constexpr T intpow(T v, unsigned p) { - if (p == 0) { - return 1; - } - - // We use exponentiation by squaring to calculate the required power. - T a = intpow(v, p / 2); - T b = (p % 2) ? v : 1; - - return a * a * b; -} - -#endif // SHARE_UTILITIES_INTPOW_HPP diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index 64f3e787356e0..7e9d557d11cb7 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -77,29 +77,11 @@ class FloatRegister(Register): def __str__(self): return self.astr("v") - def generate(self): - self.number = random.randint(0, 31) - return self - def nextReg(self): next = FloatRegister() next.number = (self.number + 1) % 32 return next -class LowFloatRegister(Register): - - def __str__(self): - return self.astr("v") - - def generate(self): - self.number = random.randint(0, 15) - return self - - def nextReg(self): - next = FloatRegister() - next.number = (self.number + 1) % 16 - return next - class GeneralRegister(Register): def __str__(self): @@ -1289,75 +1271,6 @@ def astr(self): def aname(self): return self._name -class VectorScalarNEONInstruction(Instruction): - def __init__(self, args): - self._name, self.insname, self.arrangement = args - - def generate(self): - vectorLength = {"8B" : 8, "16B" : 16, "4H" : 4, "8H" : 8, "2S" : 2, "4S" : 4, "1D" : 1, "2D" : 2} [self.arrangement] - self.elemIndex = random.randrange(0, vectorLength) - self.elemSizeSpecifier = self.arrangement[len(self.arrangement) - 1:] - self._firstSIMDreg = LowFloatRegister().generate() - self.numRegs = 3 - return self - - def cstr(self): - buf = Instruction.cstr(self) + str(self._firstSIMDreg) - buf = '%s, __ T%s' % (buf, self.arrangement) - current = self._firstSIMDreg - for cnt in range(1, self.numRegs - 1): - buf = '%s, %s' % (buf, current.nextReg()) - current = current.nextReg() - buf = '%s, %s, %d' % (buf, current.nextReg(), self.elemIndex) - return '%s);' % (buf) - - def astr(self): - buf = '%s\t%s.%s' % (self.insname, self._firstSIMDreg, self.arrangement) - current = self._firstSIMDreg - for cnt in range(1, self.numRegs - 1): - buf = '%s, %s.%s' % (buf, current.nextReg(), self.arrangement) - current = current.nextReg() - buf = '%s, %s.%s[%d]' % (buf, current.nextReg(), self.elemSizeSpecifier, self.elemIndex) - return buf - - def aname(self): - return self._name - -class WideningNEONInstruction(Instruction): - def __init__(self, args): - self._name, self.insname, self.widerArrangement, self.narrowerArrangement = args - - def generate(self): - self._firstSIMDreg = FloatRegister().generate() - return self - - def cstr(self): - buf = Instruction.cstr(self) + str(self._firstSIMDreg) - current = self._firstSIMDreg - for cnt in range(1, self.numWiderRegs): - buf = '%s, %s' % (buf, current.nextReg()) - current = current.nextReg() - buf = '%s, __ T%s' % (buf, self.widerArrangement) - for cnt in range(0, self.numNarrowerRegs): - buf = '%s, %s' % (buf, current.nextReg()) - current = current.nextReg() - buf = '%s, __ T%s' % (buf, self.narrowerArrangement) - return '%s);' % (buf) - - def astr(self): - buf = '%s\t%s.%s' % (self.insname, self._firstSIMDreg, self.widerArrangement) - current = self._firstSIMDreg - for cnt in range(1, self.numWiderRegs): - buf = '%s, %s.%s' % (buf, current.nextReg(), self.widerArrangement) - current = current.nextReg() - for cnt in range(0, self.numNarrowerRegs): - buf = '%s, %s.%s' % (buf, current.nextReg(), self.narrowerArrangement) - current = current.nextReg() - return buf - - def aname(self): - return self._name - class SHA512SIMDOp(Instruction): def generate(self): @@ -1477,10 +1390,6 @@ class TwoRegNEONOp(CommonNEONInstruction): class ThreeRegNEONOp(TwoRegNEONOp): numRegs = 3 -class AddWideNEONOp(WideningNEONInstruction): - numWiderRegs = 2 - numNarrowerRegs = 1 - class NEONFloatCompareWithZero(TwoRegNEONOp): def __init__(self, args): self._name = 'fcm' @@ -1839,17 +1748,6 @@ def generate(kind, names): ["facgt", "facgt", "2D"], ]) -generate(VectorScalarNEONInstruction, - [["fmlavs", "fmla", "2S"], ["mulvs", "mul", "4S"], - ["fmlavs", "fmla", "2D"], - ["fmlsvs", "fmls", "2S"], ["mulvs", "mul", "4S"], - ["fmlsvs", "fmls", "2D"], - ["fmulxvs", "fmulx", "2S"], ["mulvs", "mul", "4S"], - ["fmulxvs", "fmulx", "2D"], - ["mulvs", "mul", "4H"], ["mulvs", "mul", "8H"], - ["mulvs", "mul", "2S"], ["mulvs", "mul", "4S"], - ]) - neonVectorCompareInstructionPrefix = ['cm', 'fcm'] neonIntegerVectorCompareConditions = ['GT', 'GE', 'EQ', 'HI', 'HS'] neonFloatVectorCompareConditions = ['EQ', 'GT', 'GE'] @@ -2183,15 +2081,6 @@ def generate(kind, names): generate(SVEReductionOp, [["andv", 0], ["orv", 0], ["eorv", 0], ["smaxv", 0], ["sminv", 0], ["fminv", 2], ["fmaxv", 2], ["fadda", 2], ["uaddv", 0]]) -generate(AddWideNEONOp, - [["saddwv", "saddw", "8H", "8B"], ["saddwv2", "saddw2", "8H", "16B"], - ["saddwv", "saddw", "4S", "4H"], ["saddwv2", "saddw2", "4S", "8H"], - ["saddwv", "saddw", "2D", "2S"], ["saddwv2", "saddw2", "2D", "4S"], - ["uaddwv", "uaddw", "8H", "8B"], ["uaddwv2", "uaddw2", "8H", "16B"], - ["uaddwv", "uaddw", "4S", "4H"], ["uaddwv2", "uaddw2", "4S", "8H"], - ["uaddwv", "uaddw", "2D", "2S"], ["uaddwv2", "uaddw2", "2D", "4S"], - ]) - print "\n __ bind(forth);" outfile.write("forth:\n") diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index 9805a05c5c150..b8260aaf932d1 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -293,9 +293,9 @@ __ ldrshw(r5, Address(r3, 12)); // ldrsh w5, [x3, 12] __ ldrsw(r27, Address(r24, 17)); // ldrsw x27, [x24, 17] __ ldrd(v13, Address(r29, -35)); // ldr d13, [x29, -35] - __ ldrs(v23, Address(r9, -47)); // ldr s23, [x9, -47] + __ ldrs(v22, Address(r9, -47)); // ldr s22, [x9, -47] __ strd(v11, Address(r0, 9)); // str d11, [x0, 9] - __ strs(v21, Address(r0, -127)); // str s21, [x0, -127] + __ strs(v20, Address(r0, -127)); // str s20, [x0, -127] // pre // LoadStoreOp @@ -314,7 +314,7 @@ __ ldrd(v0, Address(__ pre(r14, -54))); // ldr d0, [x14, -54]! __ ldrs(v3, Address(__ pre(r1, 40))); // ldr s3, [x1, 40]! __ strd(v4, Address(__ pre(r14, -94))); // str d4, [x14, -94]! - __ strs(v18, Address(__ pre(r28, -54))); // str s18, [x28, -54]! + __ strs(v17, Address(__ pre(r28, -54))); // str s17, [x28, -54]! // post // LoadStoreOp @@ -331,8 +331,8 @@ __ ldrshw(r3, Address(__ post(r11, -48))); // ldrsh w3, [x11], -48 __ ldrsw(r25, Address(__ post(r23, 22))); // ldrsw x25, [x23], 22 __ ldrd(v0, Address(__ post(r10, -215))); // ldr d0, [x10], -215 - __ ldrs(v19, Address(__ post(r6, 55))); // ldr s19, [x6], 55 - __ strd(v14, Address(__ post(r21, -234))); // str d14, [x21], -234 + __ ldrs(v17, Address(__ post(r6, 55))); // ldr s17, [x6], 55 + __ strd(v13, Address(__ post(r21, -234))); // str d13, [x21], -234 __ strs(v0, Address(__ post(r22, -70))); // str s0, [x22], -70 // base_plus_reg @@ -349,9 +349,9 @@ __ ldrsh(r21, Address(r30, r30, Address::sxtw(1))); // ldrsh x21, [x30, w30, sxtw #1] __ ldrshw(r11, Address(r10, r28, Address::sxtw(1))); // ldrsh w11, [x10, w28, sxtw #1] __ ldrsw(r28, Address(r19, r10, Address::uxtw(0))); // ldrsw x28, [x19, w10, uxtw #0] - __ ldrd(v30, Address(r29, r14, Address::sxtw(0))); // ldr d30, [x29, w14, sxtw #0] + __ ldrd(v29, Address(r29, r14, Address::sxtw(0))); // ldr d29, [x29, w14, sxtw #0] __ ldrs(v8, Address(r5, r5, Address::sxtw(2))); // ldr s8, [x5, w5, sxtw #2] - __ strd(v25, Address(r8, r13, Address::sxtx(0))); // str d25, [x8, x13, sxtx #0] + __ strd(v24, Address(r8, r13, Address::sxtx(0))); // str d24, [x8, x13, sxtx #0] __ strs(v17, Address(r24, r26, Address::lsl(2))); // str s17, [x24, x26, lsl #2] // base_plus_scaled_offset @@ -370,7 +370,7 @@ __ ldrsw(r10, Address(r7, 6372)); // ldrsw x10, [x7, 6372] __ ldrd(v3, Address(r25, 12392)); // ldr d3, [x25, 12392] __ ldrs(v12, Address(r9, 7840)); // ldr s12, [x9, 7840] - __ strd(v24, Address(r1, 12728)); // str d24, [x1, 12728] + __ strd(v23, Address(r1, 12728)); // str d23, [x1, 12728] __ strs(v3, Address(r20, 6924)); // str s3, [x20, 6924] // pcrel @@ -484,63 +484,63 @@ __ umsubl(r13, r10, r7, r5); // umsubl x13, w10, w7, x5 // ThreeRegFloatOp - __ fabds(v30, v15, v3); // fabd s30, s15, s3 - __ fmuls(v12, v12, v16); // fmul s12, s12, s16 - __ fdivs(v31, v31, v18); // fdiv s31, s31, s18 - __ fadds(v19, v21, v16); // fadd s19, s21, s16 - __ fsubs(v15, v10, v21); // fsub s15, s10, s21 - __ fabdd(v2, v10, v28); // fabd d2, d10, d28 - __ fmuld(v7, v30, v31); // fmul d7, d30, d31 - __ fdivd(v18, v1, v2); // fdiv d18, d1, d2 + __ fabds(v29, v15, v3); // fabd s29, s15, s3 + __ fmuls(v11, v12, v15); // fmul s11, s12, s15 + __ fdivs(v30, v30, v17); // fdiv s30, s30, s17 + __ fadds(v19, v20, v15); // fadd s19, s20, s15 + __ fsubs(v15, v9, v21); // fsub s15, s9, s21 + __ fabdd(v2, v9, v27); // fabd d2, d9, d27 + __ fmuld(v7, v29, v30); // fmul d7, d29, d30 + __ fdivd(v17, v1, v2); // fdiv d17, d1, d2 __ faddd(v6, v10, v3); // fadd d6, d10, d3 - __ fsubd(v25, v11, v7); // fsub d25, d11, d7 + __ fsubd(v24, v11, v7); // fsub d24, d11, d7 // FourRegFloatOp - __ fmadds(v1, v12, v0, v3); // fmadd s1, s12, s0, s3 - __ fmsubs(v19, v29, v6, v23); // fmsub s19, s29, s6, s23 - __ fnmadds(v6, v0, v28, v27); // fnmadd s6, s0, s28, s27 - __ fnmadds(v2, v5, v7, v29); // fnmadd s2, s5, s7, s29 - __ fmaddd(v12, v25, v13, v12); // fmadd d12, d25, d13, d12 - __ fmsubd(v24, v19, v8, v18); // fmsub d24, d19, d8, d18 - __ fnmaddd(v22, v26, v21, v20); // fnmadd d22, d26, d21, d20 - __ fnmaddd(v19, v2, v30, v22); // fnmadd d19, d2, d30, d22 + __ fmadds(v1, v11, v0, v3); // fmadd s1, s11, s0, s3 + __ fmsubs(v17, v28, v6, v22); // fmsub s17, s28, s6, s22 + __ fnmadds(v6, v0, v27, v26); // fnmadd s6, s0, s27, s26 + __ fnmadds(v2, v5, v7, v28); // fnmadd s2, s5, s7, s28 + __ fmaddd(v11, v25, v13, v11); // fmadd d11, d25, d13, d11 + __ fmsubd(v23, v19, v8, v17); // fmsub d23, d19, d8, d17 + __ fnmaddd(v21, v25, v20, v19); // fnmadd d21, d25, d20, d19 + __ fnmaddd(v17, v2, v29, v22); // fnmadd d17, d2, d29, d22 // TwoRegFloatOp - __ fmovs(v8, v22); // fmov s8, s22 - __ fabss(v19, v21); // fabs s19, s21 - __ fnegs(v12, v18); // fneg s12, s18 - __ fsqrts(v21, v6); // fsqrt s21, s6 - __ fcvts(v16, v3); // fcvt d16, s3 - __ fcvtsh(v3, v29); // fcvt h3, s29 - __ fcvths(v3, v28); // fcvt s3, h28 - __ fmovd(v15, v14); // fmov d15, d14 - __ fabsd(v10, v13); // fabs d10, d13 - __ fnegd(v12, v18); // fneg d12, d18 - __ fsqrtd(v10, v26); // fsqrt d10, d26 + __ fmovs(v8, v21); // fmov s8, s21 + __ fabss(v19, v20); // fabs s19, s20 + __ fnegs(v11, v17); // fneg s11, s17 + __ fsqrts(v20, v6); // fsqrt s20, s6 + __ fcvts(v15, v3); // fcvt d15, s3 + __ fcvtsh(v3, v28); // fcvt h3, s28 + __ fcvths(v3, v27); // fcvt s3, h27 + __ fmovd(v14, v14); // fmov d14, d14 + __ fabsd(v10, v12); // fabs d10, d12 + __ fnegd(v11, v17); // fneg d11, d17 + __ fsqrtd(v10, v25); // fsqrt d10, d25 __ fcvtd(v7, v7); // fcvt s7, d7 // FloatConvertOp - __ fcvtzsw(r14, v29); // fcvtzs w14, s29 - __ fcvtzs(r0, v23); // fcvtzs x0, s23 + __ fcvtzsw(r14, v28); // fcvtzs w14, s28 + __ fcvtzs(r0, v22); // fcvtzs x0, s22 __ fcvtzdw(r0, v12); // fcvtzs w0, d12 - __ fcvtzd(r23, v14); // fcvtzs x23, d14 + __ fcvtzd(r23, v13); // fcvtzs x23, d13 __ scvtfws(v13, r7); // scvtf s13, w7 - __ scvtfs(v15, r7); // scvtf s15, x7 - __ scvtfwd(v9, r20); // scvtf d9, w20 - __ scvtfd(v19, r28); // scvtf d19, x28 + __ scvtfs(v14, r7); // scvtf s14, x7 + __ scvtfwd(v8, r20); // scvtf d8, w20 + __ scvtfd(v17, r28); // scvtf d17, x28 __ fcvtassw(r30, v16); // fcvtas w30, s16 __ fcvtasd(r2, v9); // fcvtas x2, d9 - __ fcvtmssw(r16, v21); // fcvtms w16, s21 + __ fcvtmssw(r16, v20); // fcvtms w16, s20 __ fcvtmsd(r29, v4); // fcvtms x29, d4 - __ fmovs(r1, v27); // fmov w1, s27 - __ fmovd(r24, v24); // fmov x24, d24 + __ fmovs(r1, v26); // fmov w1, s26 + __ fmovd(r24, v23); // fmov x24, d23 __ fmovs(v14, r21); // fmov s14, w21 - __ fmovd(v13, r5); // fmov d13, x5 + __ fmovd(v12, r5); // fmov d12, x5 // TwoRegFloatOp - __ fcmps(v12, v25); // fcmp s12, s25 - __ fcmpd(v25, v30); // fcmp d25, d30 - __ fcmps(v28, 0.0); // fcmp s28, #0.0 + __ fcmps(v12, v24); // fcmp s12, s24 + __ fcmpd(v24, v29); // fcmp d24, d29 + __ fcmps(v27, 0.0); // fcmp s27, #0.0 __ fcmpd(v21, 0.0); // fcmp d21, #0.0 // LoadStorePairOp @@ -573,265 +573,250 @@ // LdStNEONOp __ ld1(v0, __ T8B, Address(r11)); // ld1 {v0.8B}, [x11] __ ld1(v16, v17, __ T16B, Address(__ post(r26, 32))); // ld1 {v16.16B, v17.16B}, [x26], 32 - __ ld1(v22, v23, v24, __ T1D, Address(__ post(r26, r17))); // ld1 {v22.1D, v23.1D, v24.1D}, [x26], x17 - __ ld1(v27, v28, v29, v30, __ T8H, Address(__ post(r29, 64))); // ld1 {v27.8H, v28.8H, v29.8H, v30.8H}, [x29], 64 - __ ld1r(v22, __ T8B, Address(r6)); // ld1r {v22.8B}, [x6] - __ ld1r(v14, __ T4S, Address(__ post(r29, 4))); // ld1r {v14.4S}, [x29], 4 - __ ld1r(v22, __ T1D, Address(__ post(r12, r16))); // ld1r {v22.1D}, [x12], x16 + __ ld1(v21, v22, v23, __ T1D, Address(__ post(r26, r17))); // ld1 {v21.1D, v22.1D, v23.1D}, [x26], x17 + __ ld1(v26, v27, v28, v29, __ T8H, Address(__ post(r29, 64))); // ld1 {v26.8H, v27.8H, v28.8H, v29.8H}, [x29], 64 + __ ld1r(v21, __ T8B, Address(r6)); // ld1r {v21.8B}, [x6] + __ ld1r(v13, __ T4S, Address(__ post(r29, 4))); // ld1r {v13.4S}, [x29], 4 + __ ld1r(v21, __ T1D, Address(__ post(r12, r16))); // ld1r {v21.1D}, [x12], x16 __ ld2(v1, v2, __ T2D, Address(r0)); // ld2 {v1.2D, v2.2D}, [x0] - __ ld2(v10, v11, __ T4H, Address(__ post(r21, 16))); // ld2 {v10.4H, v11.4H}, [x21], 16 + __ ld2(v9, v10, __ T4H, Address(__ post(r21, 16))); // ld2 {v9.4H, v10.4H}, [x21], 16 __ ld2r(v7, v8, __ T16B, Address(r25)); // ld2r {v7.16B, v8.16B}, [x25] - __ ld2r(v9, v10, __ T2S, Address(__ post(r9, 8))); // ld2r {v9.2S, v10.2S}, [x9], 8 + __ ld2r(v8, v9, __ T2S, Address(__ post(r9, 8))); // ld2r {v8.2S, v9.2S}, [x9], 8 __ ld2r(v9, v10, __ T2D, Address(__ post(r12, r14))); // ld2r {v9.2D, v10.2D}, [x12], x14 __ ld3(v7, v8, v9, __ T4S, Address(__ post(r4, r17))); // ld3 {v7.4S, v8.4S, v9.4S}, [x4], x17 __ ld3(v23, v24, v25, __ T2S, Address(r17)); // ld3 {v23.2S, v24.2S, v25.2S}, [x17] - __ ld3r(v4, v5, v6, __ T8H, Address(r22)); // ld3r {v4.8H, v5.8H, v6.8H}, [x22] - __ ld3r(v13, v14, v15, __ T4S, Address(__ post(r2, 12))); // ld3r {v13.4S, v14.4S, v15.4S}, [x2], 12 - __ ld3r(v16, v17, v18, __ T1D, Address(__ post(r10, r12))); // ld3r {v16.1D, v17.1D, v18.1D}, [x10], x12 + __ ld3r(v3, v4, v5, __ T8H, Address(r22)); // ld3r {v3.8H, v4.8H, v5.8H}, [x22] + __ ld3r(v12, v13, v14, __ T4S, Address(__ post(r2, 12))); // ld3r {v12.4S, v13.4S, v14.4S}, [x2], 12 + __ ld3r(v15, v16, v17, __ T1D, Address(__ post(r10, r12))); // ld3r {v15.1D, v16.1D, v17.1D}, [x10], x12 __ ld4(v4, v5, v6, v7, __ T8H, Address(__ post(r2, 64))); // ld4 {v4.8H, v5.8H, v6.8H, v7.8H}, [x2], 64 __ ld4(v6, v7, v8, v9, __ T8B, Address(__ post(r20, r11))); // ld4 {v6.8B, v7.8B, v8.8B, v9.8B}, [x20], x11 - __ ld4r(v12, v13, v14, v15, __ T8B, Address(r12)); // ld4r {v12.8B, v13.8B, v14.8B, v15.8B}, [x12] - __ ld4r(v16, v17, v18, v19, __ T4H, Address(__ post(r17, 8))); // ld4r {v16.4H, v17.4H, v18.4H, v19.4H}, [x17], 8 + __ ld4r(v11, v12, v13, v14, __ T8B, Address(r12)); // ld4r {v11.8B, v12.8B, v13.8B, v14.8B}, [x12] + __ ld4r(v15, v16, v17, v18, __ T4H, Address(__ post(r17, 8))); // ld4r {v15.4H, v16.4H, v17.4H, v18.4H}, [x17], 8 __ ld4r(v14, v15, v16, v17, __ T2S, Address(__ post(r25, r16))); // ld4r {v14.2S, v15.2S, v16.2S, v17.2S}, [x25], x16 // NEONReduceInstruction __ addv(v20, __ T8B, v21); // addv b20, v21.8B __ addv(v1, __ T16B, v2); // addv b1, v2.16B - __ addv(v23, __ T4H, v24); // addv h23, v24.4H + __ addv(v22, __ T4H, v23); // addv h22, v23.4H __ addv(v30, __ T8H, v31); // addv h30, v31.8H __ addv(v14, __ T4S, v15); // addv s14, v15.4S __ smaxv(v2, __ T8B, v3); // smaxv b2, v3.8B __ smaxv(v6, __ T16B, v7); // smaxv b6, v7.16B __ smaxv(v3, __ T4H, v4); // smaxv h3, v4.4H - __ smaxv(v8, __ T8H, v9); // smaxv h8, v9.8H - __ smaxv(v25, __ T4S, v26); // smaxv s25, v26.4S + __ smaxv(v7, __ T8H, v8); // smaxv h7, v8.8H + __ smaxv(v24, __ T4S, v25); // smaxv s24, v25.4S __ fmaxv(v0, __ T4S, v1); // fmaxv s0, v1.4S __ sminv(v27, __ T8B, v28); // sminv b27, v28.8B - __ uminv(v30, __ T8B, v31); // uminv b30, v31.8B + __ uminv(v29, __ T8B, v30); // uminv b29, v30.8B __ sminv(v5, __ T16B, v6); // sminv b5, v6.16B __ uminv(v5, __ T16B, v6); // uminv b5, v6.16B - __ sminv(v30, __ T4H, v31); // sminv h30, v31.4H + __ sminv(v29, __ T4H, v30); // sminv h29, v30.4H __ uminv(v11, __ T4H, v12); // uminv h11, v12.4H __ sminv(v25, __ T8H, v26); // sminv h25, v26.8H __ uminv(v0, __ T8H, v1); // uminv h0, v1.8H - __ sminv(v31, __ T4S, v0); // sminv s31, v0.4S + __ sminv(v30, __ T4S, v31); // sminv s30, v31.4S __ uminv(v0, __ T4S, v1); // uminv s0, v1.4S - __ fminv(v19, __ T4S, v20); // fminv s19, v20.4S - __ fmaxp(v29, v30, __ S); // fmaxp s29, v30.2S - __ fmaxp(v26, v27, __ D); // fmaxp d26, v27.2D + __ fminv(v17, __ T4S, v18); // fminv s17, v18.4S + __ fmaxp(v28, v29, __ S); // fmaxp s28, v29.2S + __ fmaxp(v25, v26, __ D); // fmaxp d25, v26.2D __ fminp(v9, v10, __ S); // fminp s9, v10.2S - __ fminp(v26, v27, __ D); // fminp d26, v27.2D + __ fminp(v25, v26, __ D); // fminp d25, v26.2D // NEONFloatCompareWithZero __ fcm(Assembler::GT, v12, __ T2S, v13); // fcmgt v12.2S, v13.2S, #0.0 __ fcm(Assembler::GT, v15, __ T4S, v16); // fcmgt v15.4S, v16.4S, #0.0 __ fcm(Assembler::GT, v11, __ T2D, v12); // fcmgt v11.2D, v12.2D, #0.0 - __ fcm(Assembler::GE, v11, __ T2S, v12); // fcmge v11.2S, v12.2S, #0.0 - __ fcm(Assembler::GE, v18, __ T4S, v19); // fcmge v18.4S, v19.4S, #0.0 - __ fcm(Assembler::GE, v25, __ T2D, v26); // fcmge v25.2D, v26.2D, #0.0 - __ fcm(Assembler::EQ, v22, __ T2S, v23); // fcmeq v22.2S, v23.2S, #0.0 - __ fcm(Assembler::EQ, v24, __ T4S, v25); // fcmeq v24.4S, v25.4S, #0.0 + __ fcm(Assembler::GE, v10, __ T2S, v11); // fcmge v10.2S, v11.2S, #0.0 + __ fcm(Assembler::GE, v17, __ T4S, v18); // fcmge v17.4S, v18.4S, #0.0 + __ fcm(Assembler::GE, v24, __ T2D, v25); // fcmge v24.2D, v25.2D, #0.0 + __ fcm(Assembler::EQ, v21, __ T2S, v22); // fcmeq v21.2S, v22.2S, #0.0 + __ fcm(Assembler::EQ, v23, __ T4S, v24); // fcmeq v23.4S, v24.4S, #0.0 __ fcm(Assembler::EQ, v0, __ T2D, v1); // fcmeq v0.2D, v1.2D, #0.0 - __ fcm(Assembler::LT, v17, __ T2S, v18); // fcmlt v17.2S, v18.2S, #0.0 - __ fcm(Assembler::LT, v11, __ T4S, v12); // fcmlt v11.4S, v12.4S, #0.0 + __ fcm(Assembler::LT, v16, __ T2S, v17); // fcmlt v16.2S, v17.2S, #0.0 + __ fcm(Assembler::LT, v10, __ T4S, v11); // fcmlt v10.4S, v11.4S, #0.0 __ fcm(Assembler::LT, v6, __ T2D, v7); // fcmlt v6.2D, v7.2D, #0.0 - __ fcm(Assembler::LE, v29, __ T2S, v30); // fcmle v29.2S, v30.2S, #0.0 + __ fcm(Assembler::LE, v28, __ T2S, v29); // fcmle v28.2S, v29.2S, #0.0 __ fcm(Assembler::LE, v6, __ T4S, v7); // fcmle v6.4S, v7.4S, #0.0 __ fcm(Assembler::LE, v5, __ T2D, v6); // fcmle v5.2D, v6.2D, #0.0 // TwoRegNEONOp __ absr(v5, __ T8B, v6); // abs v5.8B, v6.8B - __ absr(v21, __ T16B, v22); // abs v21.16B, v22.16B - __ absr(v19, __ T4H, v20); // abs v19.4H, v20.4H - __ absr(v16, __ T8H, v17); // abs v16.8H, v17.8H - __ absr(v18, __ T2S, v19); // abs v18.2S, v19.2S - __ absr(v30, __ T4S, v31); // abs v30.4S, v31.4S - __ absr(v27, __ T2D, v28); // abs v27.2D, v28.2D + __ absr(v20, __ T16B, v21); // abs v20.16B, v21.16B + __ absr(v17, __ T4H, v18); // abs v17.4H, v18.4H + __ absr(v15, __ T8H, v16); // abs v15.8H, v16.8H + __ absr(v17, __ T2S, v18); // abs v17.2S, v18.2S + __ absr(v29, __ T4S, v30); // abs v29.4S, v30.4S + __ absr(v26, __ T2D, v27); // abs v26.2D, v27.2D __ fabs(v28, __ T2S, v29); // fabs v28.2S, v29.2S __ fabs(v1, __ T4S, v2); // fabs v1.4S, v2.4S - __ fabs(v28, __ T2D, v29); // fabs v28.2D, v29.2D - __ fneg(v1, __ T2S, v2); // fneg v1.2S, v2.2S + __ fabs(v27, __ T2D, v28); // fabs v27.2D, v28.2D + __ fneg(v0, __ T2S, v1); // fneg v0.2S, v1.2S __ fneg(v20, __ T4S, v21); // fneg v20.4S, v21.4S - __ fneg(v29, __ T2D, v30); // fneg v29.2D, v30.2D - __ fsqrt(v16, __ T2S, v17); // fsqrt v16.2S, v17.2S - __ fsqrt(v13, __ T4S, v14); // fsqrt v13.4S, v14.4S + __ fneg(v28, __ T2D, v29); // fneg v28.2D, v29.2D + __ fsqrt(v15, __ T2S, v16); // fsqrt v15.2S, v16.2S + __ fsqrt(v12, __ T4S, v13); // fsqrt v12.4S, v13.4S __ fsqrt(v10, __ T2D, v11); // fsqrt v10.2D, v11.2D - __ notr(v29, __ T8B, v30); // not v29.8B, v30.8B - __ notr(v29, __ T16B, v30); // not v29.16B, v30.16B + __ notr(v28, __ T8B, v29); // not v28.8B, v29.8B + __ notr(v28, __ T16B, v29); // not v28.16B, v29.16B // ThreeRegNEONOp __ andr(v19, __ T8B, v20, v21); // and v19.8B, v20.8B, v21.8B __ andr(v22, __ T16B, v23, v24); // and v22.16B, v23.16B, v24.16B __ orr(v10, __ T8B, v11, v12); // orr v10.8B, v11.8B, v12.8B __ orr(v4, __ T16B, v5, v6); // orr v4.16B, v5.16B, v6.16B - __ eor(v31, __ T8B, v0, v1); // eor v31.8B, v0.8B, v1.8B - __ eor(v21, __ T16B, v22, v23); // eor v21.16B, v22.16B, v23.16B + __ eor(v30, __ T8B, v31, v0); // eor v30.8B, v31.8B, v0.8B + __ eor(v20, __ T16B, v21, v22); // eor v20.16B, v21.16B, v22.16B __ addv(v8, __ T8B, v9, v10); // add v8.8B, v9.8B, v10.8B - __ addv(v31, __ T16B, v0, v1); // add v31.16B, v0.16B, v1.16B - __ addv(v19, __ T4H, v20, v21); // add v19.4H, v20.4H, v21.4H + __ addv(v30, __ T16B, v31, v0); // add v30.16B, v31.16B, v0.16B + __ addv(v17, __ T4H, v18, v19); // add v17.4H, v18.4H, v19.4H __ addv(v10, __ T8H, v11, v12); // add v10.8H, v11.8H, v12.8H - __ addv(v28, __ T2S, v29, v30); // add v28.2S, v29.2S, v30.2S + __ addv(v27, __ T2S, v28, v29); // add v27.2S, v28.2S, v29.2S __ addv(v2, __ T4S, v3, v4); // add v2.4S, v3.4S, v4.4S - __ addv(v25, __ T2D, v26, v27); // add v25.2D, v26.2D, v27.2D - __ fadd(v5, __ T2S, v6, v7); // fadd v5.2S, v6.2S, v7.2S + __ addv(v24, __ T2D, v25, v26); // add v24.2D, v25.2D, v26.2D + __ fadd(v4, __ T2S, v5, v6); // fadd v4.2S, v5.2S, v6.2S __ fadd(v3, __ T4S, v4, v5); // fadd v3.4S, v4.4S, v5.4S __ fadd(v8, __ T2D, v9, v10); // fadd v8.2D, v9.2D, v10.2D __ subv(v22, __ T8B, v23, v24); // sub v22.8B, v23.8B, v24.8B - __ subv(v19, __ T16B, v20, v21); // sub v19.16B, v20.16B, v21.16B + __ subv(v17, __ T16B, v18, v19); // sub v17.16B, v18.16B, v19.16B __ subv(v13, __ T4H, v14, v15); // sub v13.4H, v14.4H, v15.4H - __ subv(v5, __ T8H, v6, v7); // sub v5.8H, v6.8H, v7.8H - __ subv(v29, __ T2S, v30, v31); // sub v29.2S, v30.2S, v31.2S - __ subv(v24, __ T4S, v25, v26); // sub v24.4S, v25.4S, v26.4S + __ subv(v4, __ T8H, v5, v6); // sub v4.8H, v5.8H, v6.8H + __ subv(v28, __ T2S, v29, v30); // sub v28.2S, v29.2S, v30.2S + __ subv(v23, __ T4S, v24, v25); // sub v23.4S, v24.4S, v25.4S __ subv(v21, __ T2D, v22, v23); // sub v21.2D, v22.2D, v23.2D - __ fsub(v26, __ T2S, v27, v28); // fsub v26.2S, v27.2S, v28.2S + __ fsub(v25, __ T2S, v26, v27); // fsub v25.2S, v26.2S, v27.2S __ fsub(v24, __ T4S, v25, v26); // fsub v24.4S, v25.4S, v26.4S __ fsub(v3, __ T2D, v4, v5); // fsub v3.2D, v4.2D, v5.2D - __ mulv(v24, __ T8B, v25, v26); // mul v24.8B, v25.8B, v26.8B + __ mulv(v23, __ T8B, v24, v25); // mul v23.8B, v24.8B, v25.8B __ mulv(v26, __ T16B, v27, v28); // mul v26.16B, v27.16B, v28.16B __ mulv(v23, __ T4H, v24, v25); // mul v23.4H, v24.4H, v25.4H - __ mulv(v15, __ T8H, v16, v17); // mul v15.8H, v16.8H, v17.8H + __ mulv(v14, __ T8H, v15, v16); // mul v14.8H, v15.8H, v16.8H __ mulv(v21, __ T2S, v22, v23); // mul v21.2S, v22.2S, v23.2S __ mulv(v3, __ T4S, v4, v5); // mul v3.4S, v4.4S, v5.4S - __ fabd(v24, __ T2S, v25, v26); // fabd v24.2S, v25.2S, v26.2S + __ fabd(v23, __ T2S, v24, v25); // fabd v23.2S, v24.2S, v25.2S __ fabd(v8, __ T4S, v9, v10); // fabd v8.4S, v9.4S, v10.4S - __ fabd(v25, __ T2D, v26, v27); // fabd v25.2D, v26.2D, v27.2D - __ faddp(v20, __ T2S, v21, v22); // faddp v20.2S, v21.2S, v22.2S - __ faddp(v16, __ T4S, v17, v18); // faddp v16.4S, v17.4S, v18.4S - __ faddp(v17, __ T2D, v18, v19); // faddp v17.2D, v18.2D, v19.2D + __ fabd(v24, __ T2D, v25, v26); // fabd v24.2D, v25.2D, v26.2D + __ faddp(v19, __ T2S, v20, v21); // faddp v19.2S, v20.2S, v21.2S + __ faddp(v15, __ T4S, v16, v17); // faddp v15.4S, v16.4S, v17.4S + __ faddp(v16, __ T2D, v17, v18); // faddp v16.2D, v17.2D, v18.2D __ fmul(v2, __ T2S, v3, v4); // fmul v2.2S, v3.2S, v4.2S __ fmul(v1, __ T4S, v2, v3); // fmul v1.4S, v2.4S, v3.4S __ fmul(v0, __ T2D, v1, v2); // fmul v0.2D, v1.2D, v2.2D __ mlav(v24, __ T4H, v25, v26); // mla v24.4H, v25.4H, v26.4H __ mlav(v4, __ T8H, v5, v6); // mla v4.8H, v5.8H, v6.8H __ mlav(v3, __ T2S, v4, v5); // mla v3.2S, v4.2S, v5.2S - __ mlav(v12, __ T4S, v13, v14); // mla v12.4S, v13.4S, v14.4S - __ fmla(v31, __ T2S, v0, v1); // fmla v31.2S, v0.2S, v1.2S - __ fmla(v28, __ T4S, v29, v30); // fmla v28.4S, v29.4S, v30.4S - __ fmla(v10, __ T2D, v11, v12); // fmla v10.2D, v11.2D, v12.2D - __ mlsv(v26, __ T4H, v27, v28); // mls v26.4H, v27.4H, v28.4H + __ mlav(v11, __ T4S, v12, v13); // mla v11.4S, v12.4S, v13.4S + __ fmla(v30, __ T2S, v31, v0); // fmla v30.2S, v31.2S, v0.2S + __ fmla(v27, __ T4S, v28, v29); // fmla v27.4S, v28.4S, v29.4S + __ fmla(v9, __ T2D, v10, v11); // fmla v9.2D, v10.2D, v11.2D + __ mlsv(v25, __ T4H, v26, v27); // mls v25.4H, v26.4H, v27.4H __ mlsv(v2, __ T8H, v3, v4); // mls v2.8H, v3.8H, v4.8H __ mlsv(v12, __ T2S, v13, v14); // mls v12.2S, v13.2S, v14.2S - __ mlsv(v18, __ T4S, v19, v20); // mls v18.4S, v19.4S, v20.4S - __ fmls(v31, __ T2S, v0, v1); // fmls v31.2S, v0.2S, v1.2S + __ mlsv(v17, __ T4S, v18, v19); // mls v17.4S, v18.4S, v19.4S + __ fmls(v30, __ T2S, v31, v0); // fmls v30.2S, v31.2S, v0.2S __ fmls(v1, __ T4S, v2, v3); // fmls v1.4S, v2.4S, v3.4S - __ fmls(v13, __ T2D, v14, v15); // fmls v13.2D, v14.2D, v15.2D - __ fdiv(v29, __ T2S, v30, v31); // fdiv v29.2S, v30.2S, v31.2S + __ fmls(v12, __ T2D, v13, v14); // fmls v12.2D, v13.2D, v14.2D + __ fdiv(v28, __ T2S, v29, v30); // fdiv v28.2S, v29.2S, v30.2S __ fdiv(v0, __ T4S, v1, v2); // fdiv v0.4S, v1.4S, v2.4S - __ fdiv(v19, __ T2D, v20, v21); // fdiv v19.2D, v20.2D, v21.2D + __ fdiv(v17, __ T2D, v18, v19); // fdiv v17.2D, v18.2D, v19.2D __ maxv(v12, __ T8B, v13, v14); // smax v12.8B, v13.8B, v14.8B __ maxv(v17, __ T16B, v18, v19); // smax v17.16B, v18.16B, v19.16B - __ maxv(v22, __ T4H, v23, v24); // smax v22.4H, v23.4H, v24.4H - __ maxv(v13, __ T8H, v14, v15); // smax v13.8H, v14.8H, v15.8H - __ maxv(v28, __ T2S, v29, v30); // smax v28.2S, v29.2S, v30.2S - __ maxv(v30, __ T4S, v31, v0); // smax v30.4S, v31.4S, v0.4S - __ smaxp(v31, __ T8B, v0, v1); // smaxp v31.8B, v0.8B, v1.8B + __ maxv(v21, __ T4H, v22, v23); // smax v21.4H, v22.4H, v23.4H + __ maxv(v12, __ T8H, v13, v14); // smax v12.8H, v13.8H, v14.8H + __ maxv(v27, __ T2S, v28, v29); // smax v27.2S, v28.2S, v29.2S + __ maxv(v29, __ T4S, v30, v31); // smax v29.4S, v30.4S, v31.4S + __ smaxp(v30, __ T8B, v31, v0); // smaxp v30.8B, v31.8B, v0.8B __ smaxp(v1, __ T16B, v2, v3); // smaxp v1.16B, v2.16B, v3.16B - __ smaxp(v26, __ T4H, v27, v28); // smaxp v26.4H, v27.4H, v28.4H - __ smaxp(v28, __ T8H, v29, v30); // smaxp v28.8H, v29.8H, v30.8H + __ smaxp(v25, __ T4H, v26, v27); // smaxp v25.4H, v26.4H, v27.4H + __ smaxp(v27, __ T8H, v28, v29); // smaxp v27.8H, v28.8H, v29.8H __ smaxp(v4, __ T2S, v5, v6); // smaxp v4.2S, v5.2S, v6.2S - __ smaxp(v30, __ T4S, v31, v0); // smaxp v30.4S, v31.4S, v0.4S - __ fmax(v4, __ T2S, v5, v6); // fmax v4.2S, v5.2S, v6.2S + __ smaxp(v29, __ T4S, v30, v31); // smaxp v29.4S, v30.4S, v31.4S + __ fmax(v3, __ T2S, v4, v5); // fmax v3.2S, v4.2S, v5.2S __ fmax(v6, __ T4S, v7, v8); // fmax v6.4S, v7.4S, v8.4S - __ fmax(v30, __ T2D, v31, v0); // fmax v30.2D, v31.2D, v0.2D - __ minv(v26, __ T8B, v27, v28); // smin v26.8B, v27.8B, v28.8B - __ minv(v18, __ T16B, v19, v20); // smin v18.16B, v19.16B, v20.16B - __ minv(v9, __ T4H, v10, v11); // smin v9.4H, v10.4H, v11.4H - __ minv(v8, __ T8H, v9, v10); // smin v8.8H, v9.8H, v10.8H + __ fmax(v29, __ T2D, v30, v31); // fmax v29.2D, v30.2D, v31.2D + __ minv(v25, __ T8B, v26, v27); // smin v25.8B, v26.8B, v27.8B + __ minv(v17, __ T16B, v18, v19); // smin v17.16B, v18.16B, v19.16B + __ minv(v8, __ T4H, v9, v10); // smin v8.4H, v9.4H, v10.4H + __ minv(v7, __ T8H, v8, v9); // smin v7.8H, v8.8H, v9.8H __ minv(v12, __ T2S, v13, v14); // smin v12.2S, v13.2S, v14.2S __ minv(v0, __ T4S, v1, v2); // smin v0.4S, v1.4S, v2.4S - __ sminp(v20, __ T8B, v21, v22); // sminp v20.8B, v21.8B, v22.8B + __ sminp(v19, __ T8B, v20, v21); // sminp v19.8B, v20.8B, v21.8B __ sminp(v1, __ T16B, v2, v3); // sminp v1.16B, v2.16B, v3.16B - __ sminp(v24, __ T4H, v25, v26); // sminp v24.4H, v25.4H, v26.4H + __ sminp(v23, __ T4H, v24, v25); // sminp v23.4H, v24.4H, v25.4H __ sminp(v2, __ T8H, v3, v4); // sminp v2.8H, v3.8H, v4.8H __ sminp(v0, __ T2S, v1, v2); // sminp v0.2S, v1.2S, v2.2S - __ sminp(v9, __ T4S, v10, v11); // sminp v9.4S, v10.4S, v11.4S - __ fmin(v24, __ T2S, v25, v26); // fmin v24.2S, v25.2S, v26.2S - __ fmin(v26, __ T4S, v27, v28); // fmin v26.4S, v27.4S, v28.4S - __ fmin(v16, __ T2D, v17, v18); // fmin v16.2D, v17.2D, v18.2D - __ facgt(v30, __ T2S, v31, v0); // facgt v30.2S, v31.2S, v0.2S + __ sminp(v8, __ T4S, v9, v10); // sminp v8.4S, v9.4S, v10.4S + __ fmin(v23, __ T2S, v24, v25); // fmin v23.2S, v24.2S, v25.2S + __ fmin(v25, __ T4S, v26, v27); // fmin v25.4S, v26.4S, v27.4S + __ fmin(v15, __ T2D, v16, v17); // fmin v15.2D, v16.2D, v17.2D + __ facgt(v29, __ T2S, v30, v31); // facgt v29.2S, v30.2S, v31.2S __ facgt(v3, __ T4S, v4, v5); // facgt v3.4S, v4.4S, v5.4S __ facgt(v10, __ T2D, v11, v12); // facgt v10.2D, v11.2D, v12.2D -// VectorScalarNEONInstruction - __ fmlavs(v5, __ T2S, v6, v7, 1); // fmla v5.2S, v6.2S, v7.S[1] - __ mulvs(v9, __ T4S, v10, v11, 0); // mul v9.4S, v10.4S, v11.S[0] - __ fmlavs(v5, __ T2D, v6, v7, 0); // fmla v5.2D, v6.2D, v7.D[0] - __ fmlsvs(v5, __ T2S, v6, v7, 0); // fmls v5.2S, v6.2S, v7.S[0] - __ mulvs(v8, __ T4S, v9, v10, 1); // mul v8.4S, v9.4S, v10.S[1] - __ fmlsvs(v5, __ T2D, v6, v7, 0); // fmls v5.2D, v6.2D, v7.D[0] - __ fmulxvs(v6, __ T2S, v7, v8, 0); // fmulx v6.2S, v7.2S, v8.S[0] - __ mulvs(v6, __ T4S, v7, v8, 1); // mul v6.4S, v7.4S, v8.S[1] - __ fmulxvs(v3, __ T2D, v4, v5, 0); // fmulx v3.2D, v4.2D, v5.D[0] - __ mulvs(v13, __ T4H, v14, v15, 2); // mul v13.4H, v14.4H, v15.H[2] - __ mulvs(v2, __ T8H, v3, v4, 4); // mul v2.8H, v3.8H, v4.H[4] - __ mulvs(v2, __ T2S, v3, v4, 0); // mul v2.2S, v3.2S, v4.S[0] - __ mulvs(v9, __ T4S, v10, v11, 1); // mul v9.4S, v10.4S, v11.S[1] - // NEONVectorCompare - __ cm(Assembler::GT, v21, __ T8B, v22, v23); // cmgt v21.8B, v22.8B, v23.8B - __ cm(Assembler::GT, v16, __ T16B, v17, v18); // cmgt v16.16B, v17.16B, v18.16B - __ cm(Assembler::GT, v18, __ T4H, v19, v20); // cmgt v18.4H, v19.4H, v20.4H - __ cm(Assembler::GT, v11, __ T8H, v12, v13); // cmgt v11.8H, v12.8H, v13.8H - __ cm(Assembler::GT, v21, __ T2S, v22, v23); // cmgt v21.2S, v22.2S, v23.2S - __ cm(Assembler::GT, v23, __ T4S, v24, v25); // cmgt v23.4S, v24.4S, v25.4S - __ cm(Assembler::GT, v12, __ T2D, v13, v14); // cmgt v12.2D, v13.2D, v14.2D - __ cm(Assembler::GE, v26, __ T8B, v27, v28); // cmge v26.8B, v27.8B, v28.8B - __ cm(Assembler::GE, v23, __ T16B, v24, v25); // cmge v23.16B, v24.16B, v25.16B - __ cm(Assembler::GE, v28, __ T4H, v29, v30); // cmge v28.4H, v29.4H, v30.4H - __ cm(Assembler::GE, v14, __ T8H, v15, v16); // cmge v14.8H, v15.8H, v16.8H - __ cm(Assembler::GE, v11, __ T2S, v12, v13); // cmge v11.2S, v12.2S, v13.2S - __ cm(Assembler::GE, v24, __ T4S, v25, v26); // cmge v24.4S, v25.4S, v26.4S - __ cm(Assembler::GE, v1, __ T2D, v2, v3); // cmge v1.2D, v2.2D, v3.2D - __ cm(Assembler::EQ, v12, __ T8B, v13, v14); // cmeq v12.8B, v13.8B, v14.8B - __ cm(Assembler::EQ, v31, __ T16B, v0, v1); // cmeq v31.16B, v0.16B, v1.16B - __ cm(Assembler::EQ, v10, __ T4H, v11, v12); // cmeq v10.4H, v11.4H, v12.4H - __ cm(Assembler::EQ, v16, __ T8H, v17, v18); // cmeq v16.8H, v17.8H, v18.8H - __ cm(Assembler::EQ, v7, __ T2S, v8, v9); // cmeq v7.2S, v8.2S, v9.2S - __ cm(Assembler::EQ, v2, __ T4S, v3, v4); // cmeq v2.4S, v3.4S, v4.4S - __ cm(Assembler::EQ, v3, __ T2D, v4, v5); // cmeq v3.2D, v4.2D, v5.2D - __ cm(Assembler::HI, v13, __ T8B, v14, v15); // cmhi v13.8B, v14.8B, v15.8B - __ cm(Assembler::HI, v19, __ T16B, v20, v21); // cmhi v19.16B, v20.16B, v21.16B - __ cm(Assembler::HI, v17, __ T4H, v18, v19); // cmhi v17.4H, v18.4H, v19.4H - __ cm(Assembler::HI, v16, __ T8H, v17, v18); // cmhi v16.8H, v17.8H, v18.8H - __ cm(Assembler::HI, v3, __ T2S, v4, v5); // cmhi v3.2S, v4.2S, v5.2S - __ cm(Assembler::HI, v1, __ T4S, v2, v3); // cmhi v1.4S, v2.4S, v3.4S - __ cm(Assembler::HI, v11, __ T2D, v12, v13); // cmhi v11.2D, v12.2D, v13.2D - __ cm(Assembler::HS, v30, __ T8B, v31, v0); // cmhs v30.8B, v31.8B, v0.8B - __ cm(Assembler::HS, v5, __ T16B, v6, v7); // cmhs v5.16B, v6.16B, v7.16B - __ cm(Assembler::HS, v8, __ T4H, v9, v10); // cmhs v8.4H, v9.4H, v10.4H - __ cm(Assembler::HS, v15, __ T8H, v16, v17); // cmhs v15.8H, v16.8H, v17.8H - __ cm(Assembler::HS, v29, __ T2S, v30, v31); // cmhs v29.2S, v30.2S, v31.2S - __ cm(Assembler::HS, v30, __ T4S, v31, v0); // cmhs v30.4S, v31.4S, v0.4S - __ cm(Assembler::HS, v0, __ T2D, v1, v2); // cmhs v0.2D, v1.2D, v2.2D - __ fcm(Assembler::EQ, v20, __ T2S, v21, v22); // fcmeq v20.2S, v21.2S, v22.2S - __ fcm(Assembler::EQ, v7, __ T4S, v8, v9); // fcmeq v7.4S, v8.4S, v9.4S - __ fcm(Assembler::EQ, v20, __ T2D, v21, v22); // fcmeq v20.2D, v21.2D, v22.2D - __ fcm(Assembler::GT, v23, __ T2S, v24, v25); // fcmgt v23.2S, v24.2S, v25.2S - __ fcm(Assembler::GT, v28, __ T4S, v29, v30); // fcmgt v28.4S, v29.4S, v30.4S - __ fcm(Assembler::GT, v21, __ T2D, v22, v23); // fcmgt v21.2D, v22.2D, v23.2D - __ fcm(Assembler::GE, v27, __ T2S, v28, v29); // fcmge v27.2S, v28.2S, v29.2S - __ fcm(Assembler::GE, v25, __ T4S, v26, v27); // fcmge v25.4S, v26.4S, v27.4S - __ fcm(Assembler::GE, v5, __ T2D, v6, v7); // fcmge v5.2D, v6.2D, v7.2D + __ cm(Assembler::GT, v22, __ T8B, v23, v24); // cmgt v22.8B, v23.8B, v24.8B + __ cm(Assembler::GT, v10, __ T16B, v11, v12); // cmgt v10.16B, v11.16B, v12.16B + __ cm(Assembler::GT, v4, __ T4H, v5, v6); // cmgt v4.4H, v5.4H, v6.4H + __ cm(Assembler::GT, v17, __ T8H, v18, v19); // cmgt v17.8H, v18.8H, v19.8H + __ cm(Assembler::GT, v1, __ T2S, v2, v3); // cmgt v1.2S, v2.2S, v3.2S + __ cm(Assembler::GT, v11, __ T4S, v12, v13); // cmgt v11.4S, v12.4S, v13.4S + __ cm(Assembler::GT, v7, __ T2D, v8, v9); // cmgt v7.2D, v8.2D, v9.2D + __ cm(Assembler::GE, v10, __ T8B, v11, v12); // cmge v10.8B, v11.8B, v12.8B + __ cm(Assembler::GE, v15, __ T16B, v16, v17); // cmge v15.16B, v16.16B, v17.16B + __ cm(Assembler::GE, v16, __ T4H, v17, v18); // cmge v16.4H, v17.4H, v18.4H + __ cm(Assembler::GE, v2, __ T8H, v3, v4); // cmge v2.8H, v3.8H, v4.8H + __ cm(Assembler::GE, v9, __ T2S, v10, v11); // cmge v9.2S, v10.2S, v11.2S + __ cm(Assembler::GE, v11, __ T4S, v12, v13); // cmge v11.4S, v12.4S, v13.4S + __ cm(Assembler::GE, v12, __ T2D, v13, v14); // cmge v12.2D, v13.2D, v14.2D + __ cm(Assembler::EQ, v14, __ T8B, v15, v16); // cmeq v14.8B, v15.8B, v16.8B + __ cm(Assembler::EQ, v13, __ T16B, v14, v15); // cmeq v13.16B, v14.16B, v15.16B + __ cm(Assembler::EQ, v2, __ T4H, v3, v4); // cmeq v2.4H, v3.4H, v4.4H + __ cm(Assembler::EQ, v6, __ T8H, v7, v8); // cmeq v6.8H, v7.8H, v8.8H + __ cm(Assembler::EQ, v19, __ T2S, v20, v21); // cmeq v19.2S, v20.2S, v21.2S + __ cm(Assembler::EQ, v25, __ T4S, v26, v27); // cmeq v25.4S, v26.4S, v27.4S + __ cm(Assembler::EQ, v15, __ T2D, v16, v17); // cmeq v15.2D, v16.2D, v17.2D + __ cm(Assembler::HI, v4, __ T8B, v5, v6); // cmhi v4.8B, v5.8B, v6.8B + __ cm(Assembler::HI, v2, __ T16B, v3, v4); // cmhi v2.16B, v3.16B, v4.16B + __ cm(Assembler::HI, v4, __ T4H, v5, v6); // cmhi v4.4H, v5.4H, v6.4H + __ cm(Assembler::HI, v11, __ T8H, v12, v13); // cmhi v11.8H, v12.8H, v13.8H + __ cm(Assembler::HI, v17, __ T2S, v18, v19); // cmhi v17.2S, v18.2S, v19.2S + __ cm(Assembler::HI, v20, __ T4S, v21, v22); // cmhi v20.4S, v21.4S, v22.4S + __ cm(Assembler::HI, v16, __ T2D, v17, v18); // cmhi v16.2D, v17.2D, v18.2D + __ cm(Assembler::HS, v17, __ T8B, v18, v19); // cmhs v17.8B, v18.8B, v19.8B + __ cm(Assembler::HS, v10, __ T16B, v11, v12); // cmhs v10.16B, v11.16B, v12.16B + __ cm(Assembler::HS, v20, __ T4H, v21, v22); // cmhs v20.4H, v21.4H, v22.4H + __ cm(Assembler::HS, v22, __ T8H, v23, v24); // cmhs v22.8H, v23.8H, v24.8H + __ cm(Assembler::HS, v12, __ T2S, v13, v14); // cmhs v12.2S, v13.2S, v14.2S + __ cm(Assembler::HS, v25, __ T4S, v26, v27); // cmhs v25.4S, v26.4S, v27.4S + __ cm(Assembler::HS, v23, __ T2D, v24, v25); // cmhs v23.2D, v24.2D, v25.2D + __ fcm(Assembler::EQ, v28, __ T2S, v29, v30); // fcmeq v28.2S, v29.2S, v30.2S + __ fcm(Assembler::EQ, v14, __ T4S, v15, v16); // fcmeq v14.4S, v15.4S, v16.4S + __ fcm(Assembler::EQ, v10, __ T2D, v11, v12); // fcmeq v10.2D, v11.2D, v12.2D + __ fcm(Assembler::GT, v24, __ T2S, v25, v26); // fcmgt v24.2S, v25.2S, v26.2S + __ fcm(Assembler::GT, v1, __ T4S, v2, v3); // fcmgt v1.4S, v2.4S, v3.4S + __ fcm(Assembler::GT, v11, __ T2D, v12, v13); // fcmgt v11.2D, v12.2D, v13.2D + __ fcm(Assembler::GE, v30, __ T2S, v31, v0); // fcmge v30.2S, v31.2S, v0.2S + __ fcm(Assembler::GE, v10, __ T4S, v11, v12); // fcmge v10.4S, v11.4S, v12.4S + __ fcm(Assembler::GE, v15, __ T2D, v16, v17); // fcmge v15.2D, v16.2D, v17.2D // SVEComparisonWithZero - __ sve_fcm(Assembler::EQ, p0, __ D, p7, z23, 0.0); // fcmeq p0.d, p7/z, z23.d, #0.0 - __ sve_fcm(Assembler::GT, p2, __ S, p7, z12, 0.0); // fcmgt p2.s, p7/z, z12.s, #0.0 - __ sve_fcm(Assembler::GE, p7, __ D, p7, z29, 0.0); // fcmge p7.d, p7/z, z29.d, #0.0 - __ sve_fcm(Assembler::LT, p9, __ S, p3, z31, 0.0); // fcmlt p9.s, p3/z, z31.s, #0.0 - __ sve_fcm(Assembler::LE, p9, __ D, p6, z31, 0.0); // fcmle p9.d, p6/z, z31.d, #0.0 - __ sve_fcm(Assembler::NE, p10, __ S, p2, z16, 0.0); // fcmne p10.s, p2/z, z16.s, #0.0 + __ sve_fcm(Assembler::EQ, p3, __ S, p3, z2, 0.0); // fcmeq p3.s, p3/z, z2.s, #0.0 + __ sve_fcm(Assembler::GT, p9, __ D, p0, z16, 0.0); // fcmgt p9.d, p0/z, z16.d, #0.0 + __ sve_fcm(Assembler::GE, p0, __ D, p1, z11, 0.0); // fcmge p0.d, p1/z, z11.d, #0.0 + __ sve_fcm(Assembler::LT, p4, __ D, p7, z14, 0.0); // fcmlt p4.d, p7/z, z14.d, #0.0 + __ sve_fcm(Assembler::LE, p0, __ S, p5, z20, 0.0); // fcmle p0.s, p5/z, z20.s, #0.0 + __ sve_fcm(Assembler::NE, p11, __ D, p6, z27, 0.0); // fcmne p11.d, p6/z, z27.d, #0.0 // SVEComparisonWithImm - __ sve_cmp(Assembler::EQ, p4, __ D, p4, z6, 11); // cmpeq p4.d, p4/z, z6.d, #11 - __ sve_cmp(Assembler::GT, p14, __ B, p2, z30, 4); // cmpgt p14.b, p2/z, z30.b, #4 - __ sve_cmp(Assembler::GE, p5, __ D, p4, z4, 1); // cmpge p5.d, p4/z, z4.d, #1 - __ sve_cmp(Assembler::LT, p11, __ D, p3, z3, 6); // cmplt p11.d, p3/z, z3.d, #6 - __ sve_cmp(Assembler::LE, p9, __ S, p0, z19, -1); // cmple p9.s, p0/z, z19.s, #-1 - __ sve_cmp(Assembler::NE, p3, __ S, p2, z12, -3); // cmpne p3.s, p2/z, z12.s, #-3 - __ sve_cmp(Assembler::HS, p11, __ D, p4, z1, 20); // cmphs p11.d, p4/z, z1.d, #20 - __ sve_cmp(Assembler::HI, p8, __ S, p5, z2, 53); // cmphi p8.s, p5/z, z2.s, #53 - __ sve_cmp(Assembler::LS, p5, __ D, p6, z21, 49); // cmpls p5.d, p6/z, z21.d, #49 - __ sve_cmp(Assembler::LO, p13, __ B, p7, z3, 97); // cmplo p13.b, p7/z, z3.b, #97 + __ sve_cmp(Assembler::EQ, p12, __ B, p5, z4, 0); // cmpeq p12.b, p5/z, z4.b, #0 + __ sve_cmp(Assembler::GT, p15, __ H, p2, z5, 12); // cmpgt p15.h, p2/z, z5.h, #12 + __ sve_cmp(Assembler::GE, p7, __ S, p7, z28, 3); // cmpge p7.s, p7/z, z28.s, #3 + __ sve_cmp(Assembler::LT, p15, __ H, p4, z5, 15); // cmplt p15.h, p4/z, z5.h, #15 + __ sve_cmp(Assembler::LE, p9, __ S, p4, z26, -4); // cmple p9.s, p4/z, z26.s, #-4 + __ sve_cmp(Assembler::NE, p5, __ B, p7, z9, 1); // cmpne p5.b, p7/z, z9.b, #1 + __ sve_cmp(Assembler::HS, p13, __ D, p1, z27, 43); // cmphs p13.d, p1/z, z27.d, #43 + __ sve_cmp(Assembler::HI, p10, __ B, p6, z9, 70); // cmphi p10.b, p6/z, z9.b, #70 + __ sve_cmp(Assembler::LS, p8, __ B, p7, z22, 61); // cmpls p8.b, p7/z, z22.b, #61 + __ sve_cmp(Assembler::LO, p11, __ S, p5, z17, 11); // cmplo p11.s, p5/z, z17.s, #11 // SpecialCases __ ccmn(zr, zr, 3u, Assembler::LE); // ccmn xzr, xzr, #3, LE @@ -1086,229 +1071,215 @@ __ fmovd(v0, -1.0625); // fmov d0, #-1.0625 // LSEOp - __ swp(Assembler::xword, r19, r17, r9); // swp x19, x17, [x9] - __ ldadd(Assembler::xword, r28, r27, r15); // ldadd x28, x27, [x15] - __ ldbic(Assembler::xword, r7, r21, r23); // ldclr x7, x21, [x23] - __ ldeor(Assembler::xword, zr, r25, r2); // ldeor xzr, x25, [x2] - __ ldorr(Assembler::xword, zr, r27, r15); // ldset xzr, x27, [x15] - __ ldsmin(Assembler::xword, r10, r23, r19); // ldsmin x10, x23, [x19] - __ ldsmax(Assembler::xword, r3, r16, r0); // ldsmax x3, x16, [x0] - __ ldumin(Assembler::xword, r25, r26, r23); // ldumin x25, x26, [x23] - __ ldumax(Assembler::xword, r2, r16, r12); // ldumax x2, x16, [x12] + __ swp(Assembler::xword, r15, r6, r12); // swp x15, x6, [x12] + __ ldadd(Assembler::xword, r16, r11, r13); // ldadd x16, x11, [x13] + __ ldbic(Assembler::xword, r23, r1, r30); // ldclr x23, x1, [x30] + __ ldeor(Assembler::xword, r19, r5, r17); // ldeor x19, x5, [x17] + __ ldorr(Assembler::xword, r2, r16, r22); // ldset x2, x16, [x22] + __ ldsmin(Assembler::xword, r13, r10, r21); // ldsmin x13, x10, [x21] + __ ldsmax(Assembler::xword, r29, r27, r12); // ldsmax x29, x27, [x12] + __ ldumin(Assembler::xword, r27, r3, r1); // ldumin x27, x3, [x1] + __ ldumax(Assembler::xword, zr, r24, r19); // ldumax xzr, x24, [x19] // LSEOp - __ swpa(Assembler::xword, r4, r28, r30); // swpa x4, x28, [x30] - __ ldadda(Assembler::xword, r29, r16, r27); // ldadda x29, x16, [x27] - __ ldbica(Assembler::xword, r6, r9, r29); // ldclra x6, x9, [x29] - __ ldeora(Assembler::xword, r16, r7, r4); // ldeora x16, x7, [x4] - __ ldorra(Assembler::xword, r7, r15, r9); // ldseta x7, x15, [x9] - __ ldsmina(Assembler::xword, r23, r8, r2); // ldsmina x23, x8, [x2] - __ ldsmaxa(Assembler::xword, r28, r21, sp); // ldsmaxa x28, x21, [sp] - __ ldumina(Assembler::xword, r5, r27, r0); // ldumina x5, x27, [x0] - __ ldumaxa(Assembler::xword, r17, r15, r4); // ldumaxa x17, x15, [x4] + __ swpa(Assembler::xword, r17, r9, r28); // swpa x17, x9, [x28] + __ ldadda(Assembler::xword, r27, r15, r7); // ldadda x27, x15, [x7] + __ ldbica(Assembler::xword, r21, r23, sp); // ldclra x21, x23, [sp] + __ ldeora(Assembler::xword, r25, r2, sp); // ldeora x25, x2, [sp] + __ ldorra(Assembler::xword, r27, r16, r10); // ldseta x27, x16, [x10] + __ ldsmina(Assembler::xword, r23, r19, r3); // ldsmina x23, x19, [x3] + __ ldsmaxa(Assembler::xword, r16, r0, r25); // ldsmaxa x16, x0, [x25] + __ ldumina(Assembler::xword, r26, r23, r2); // ldumina x26, x23, [x2] + __ ldumaxa(Assembler::xword, r16, r12, r4); // ldumaxa x16, x12, [x4] // LSEOp - __ swpal(Assembler::xword, r26, r8, r28); // swpal x26, x8, [x28] - __ ldaddal(Assembler::xword, r22, r27, r27); // ldaddal x22, x27, [x27] - __ ldbical(Assembler::xword, r25, r23, r0); // ldclral x25, x23, [x0] - __ ldeoral(Assembler::xword, r4, r6, r15); // ldeoral x4, x6, [x15] - __ ldorral(Assembler::xword, r0, r4, r15); // ldsetal x0, x4, [x15] - __ ldsminal(Assembler::xword, r1, r10, r7); // ldsminal x1, x10, [x7] - __ ldsmaxal(Assembler::xword, r5, r10, r28); // ldsmaxal x5, x10, [x28] - __ lduminal(Assembler::xword, r7, r20, r23); // lduminal x7, x20, [x23] - __ ldumaxal(Assembler::xword, r21, r6, r11); // ldumaxal x21, x6, [x11] + __ swpal(Assembler::xword, r28, r30, r29); // swpal x28, x30, [x29] + __ ldaddal(Assembler::xword, r16, r27, r6); // ldaddal x16, x27, [x6] + __ ldbical(Assembler::xword, r9, r29, r15); // ldclral x9, x29, [x15] + __ ldeoral(Assembler::xword, r7, r4, r7); // ldeoral x7, x4, [x7] + __ ldorral(Assembler::xword, r15, r9, r23); // ldsetal x15, x9, [x23] + __ ldsminal(Assembler::xword, r8, r2, r28); // ldsminal x8, x2, [x28] + __ ldsmaxal(Assembler::xword, r21, zr, r5); // ldsmaxal x21, xzr, [x5] + __ lduminal(Assembler::xword, r27, r0, r17); // lduminal x27, x0, [x17] + __ ldumaxal(Assembler::xword, r15, r4, r26); // ldumaxal x15, x4, [x26] // LSEOp - __ swpl(Assembler::xword, r8, r17, sp); // swpl x8, x17, [sp] - __ ldaddl(Assembler::xword, r6, r17, r2); // ldaddl x6, x17, [x2] - __ ldbicl(Assembler::xword, r12, r30, r29); // ldclrl x12, x30, [x29] - __ ldeorl(Assembler::xword, r3, r27, r22); // ldeorl x3, x27, [x22] - __ ldorrl(Assembler::xword, r29, r14, r13); // ldsetl x29, x14, [x13] - __ ldsminl(Assembler::xword, r28, r17, r24); // ldsminl x28, x17, [x24] - __ ldsmaxl(Assembler::xword, r5, r2, r14); // ldsmaxl x5, x2, [x14] - __ lduminl(Assembler::xword, r10, r16, r11); // lduminl x10, x16, [x11] - __ ldumaxl(Assembler::xword, r27, r23, r12); // ldumaxl x27, x23, [x12] + __ swpl(Assembler::xword, r8, r28, r22); // swpl x8, x28, [x22] + __ ldaddl(Assembler::xword, r27, r27, r25); // ldaddl x27, x27, [x25] + __ ldbicl(Assembler::xword, r23, r0, r4); // ldclrl x23, x0, [x4] + __ ldeorl(Assembler::xword, r6, r16, r0); // ldeorl x6, x16, [x0] + __ ldorrl(Assembler::xword, r4, r15, r1); // ldsetl x4, x15, [x1] + __ ldsminl(Assembler::xword, r10, r7, r5); // ldsminl x10, x7, [x5] + __ ldsmaxl(Assembler::xword, r10, r28, r7); // ldsmaxl x10, x28, [x7] + __ lduminl(Assembler::xword, r20, r23, r21); // lduminl x20, x23, [x21] + __ ldumaxl(Assembler::xword, r6, r11, r8); // ldumaxl x6, x11, [x8] // LSEOp - __ swp(Assembler::word, r4, r22, r17); // swp w4, w22, [x17] - __ ldadd(Assembler::word, r4, r1, r19); // ldadd w4, w1, [x19] - __ ldbic(Assembler::word, r16, r16, r13); // ldclr w16, w16, [x13] - __ ldeor(Assembler::word, r14, r12, r2); // ldeor w14, w12, [x2] - __ ldorr(Assembler::word, r17, r3, r21); // ldset w17, w3, [x21] - __ ldsmin(Assembler::word, r23, r5, r6); // ldsmin w23, w5, [x6] - __ ldsmax(Assembler::word, r7, r19, r13); // ldsmax w7, w19, [x13] - __ ldumin(Assembler::word, r28, r17, r16); // ldumin w28, w17, [x16] - __ ldumax(Assembler::word, r6, r2, r29); // ldumax w6, w2, [x29] + __ swp(Assembler::word, r17, zr, r6); // swp w17, wzr, [x6] + __ ldadd(Assembler::word, r17, r2, r12); // ldadd w17, w2, [x12] + __ ldbic(Assembler::word, r30, r29, r3); // ldclr w30, w29, [x3] + __ ldeor(Assembler::word, r27, r22, r29); // ldeor w27, w22, [x29] + __ ldorr(Assembler::word, r14, r13, r28); // ldset w14, w13, [x28] + __ ldsmin(Assembler::word, r17, r24, r5); // ldsmin w17, w24, [x5] + __ ldsmax(Assembler::word, r2, r14, r10); // ldsmax w2, w14, [x10] + __ ldumin(Assembler::word, r16, r11, r27); // ldumin w16, w11, [x27] + __ ldumax(Assembler::word, r23, r12, r4); // ldumax w23, w12, [x4] // LSEOp - __ swpa(Assembler::word, r3, r4, r6); // swpa w3, w4, [x6] - __ ldadda(Assembler::word, r16, r20, r13); // ldadda w16, w20, [x13] - __ ldbica(Assembler::word, r12, r20, r8); // ldclra w12, w20, [x8] - __ ldeora(Assembler::word, r25, r20, r19); // ldeora w25, w20, [x19] - __ ldorra(Assembler::word, r0, r11, r24); // ldseta w0, w11, [x24] - __ ldsmina(Assembler::word, r6, r20, sp); // ldsmina w6, w20, [sp] - __ ldsmaxa(Assembler::word, r14, r16, r6); // ldsmaxa w14, w16, [x6] - __ ldumina(Assembler::word, r0, r7, r15); // ldumina w0, w7, [x15] - __ ldumaxa(Assembler::word, r19, r26, r9); // ldumaxa w19, w26, [x9] + __ swpa(Assembler::word, r22, r17, r4); // swpa w22, w17, [x4] + __ ldadda(Assembler::word, r1, r19, r16); // ldadda w1, w19, [x16] + __ ldbica(Assembler::word, r16, r13, r14); // ldclra w16, w13, [x14] + __ ldeora(Assembler::word, r12, r2, r17); // ldeora w12, w2, [x17] + __ ldorra(Assembler::word, r3, r21, r23); // ldseta w3, w21, [x23] + __ ldsmina(Assembler::word, r5, r6, r7); // ldsmina w5, w6, [x7] + __ ldsmaxa(Assembler::word, r19, r13, r28); // ldsmaxa w19, w13, [x28] + __ ldumina(Assembler::word, r17, r16, r6); // ldumina w17, w16, [x6] + __ ldumaxa(Assembler::word, r2, r29, r3); // ldumaxa w2, w29, [x3] // LSEOp - __ swpal(Assembler::word, r10, r23, r21); // swpal w10, w23, [x21] - __ ldaddal(Assembler::word, r22, r28, r2); // ldaddal w22, w28, [x2] - __ ldbical(Assembler::word, r3, r15, r19); // ldclral w3, w15, [x19] - __ ldeoral(Assembler::word, r20, r7, r4); // ldeoral w20, w7, [x4] - __ ldorral(Assembler::word, r29, r7, r0); // ldsetal w29, w7, [x0] - __ ldsminal(Assembler::word, r9, r16, r20); // ldsminal w9, w16, [x20] - __ ldsmaxal(Assembler::word, r23, r4, r16); // ldsmaxal w23, w4, [x16] - __ lduminal(Assembler::word, r10, r23, r11); // lduminal w10, w23, [x11] - __ ldumaxal(Assembler::word, r25, r6, sp); // ldumaxal w25, w6, [sp] + __ swpal(Assembler::word, r4, r6, r15); // swpal w4, w6, [x15] + __ ldaddal(Assembler::word, r20, r13, r12); // ldaddal w20, w13, [x12] + __ ldbical(Assembler::word, r20, r8, r25); // ldclral w20, w8, [x25] + __ ldeoral(Assembler::word, r20, r19, r0); // ldeoral w20, w19, [x0] + __ ldorral(Assembler::word, r11, r24, r6); // ldsetal w11, w24, [x6] + __ ldsminal(Assembler::word, r20, zr, r14); // ldsminal w20, wzr, [x14] + __ ldsmaxal(Assembler::word, r16, r6, r0); // ldsmaxal w16, w6, [x0] + __ lduminal(Assembler::word, r7, r15, r19); // lduminal w7, w15, [x19] + __ ldumaxal(Assembler::word, r26, r9, r10); // ldumaxal w26, w9, [x10] // LSEOp - __ swpl(Assembler::word, r16, r13, r23); // swpl w16, w13, [x23] - __ ldaddl(Assembler::word, r12, r1, r14); // ldaddl w12, w1, [x14] - __ ldbicl(Assembler::word, r9, r21, r16); // ldclrl w9, w21, [x16] - __ ldeorl(Assembler::word, r26, r15, r4); // ldeorl w26, w15, [x4] - __ ldorrl(Assembler::word, r4, r16, r8); // ldsetl w4, w16, [x8] - __ ldsminl(Assembler::word, r6, r30, r4); // ldsminl w6, w30, [x4] - __ ldsmaxl(Assembler::word, r29, r17, r29); // ldsmaxl w29, w17, [x29] - __ lduminl(Assembler::word, r26, r9, r15); // lduminl w26, w9, [x15] - __ ldumaxl(Assembler::word, r2, r11, r29); // ldumaxl w2, w11, [x29] + __ swpl(Assembler::word, r23, r21, r22); // swpl w23, w21, [x22] + __ ldaddl(Assembler::word, r28, r2, r3); // ldaddl w28, w2, [x3] + __ ldbicl(Assembler::word, r15, r19, r20); // ldclrl w15, w19, [x20] + __ ldeorl(Assembler::word, r7, r4, r29); // ldeorl w7, w4, [x29] + __ ldorrl(Assembler::word, r7, r0, r9); // ldsetl w7, w0, [x9] + __ ldsminl(Assembler::word, r16, r20, r23); // ldsminl w16, w20, [x23] + __ ldsmaxl(Assembler::word, r4, r16, r10); // ldsmaxl w4, w16, [x10] + __ lduminl(Assembler::word, r23, r11, r25); // lduminl w23, w11, [x25] + __ ldumaxl(Assembler::word, r6, zr, r16); // ldumaxl w6, wzr, [x16] // SHA3SIMDOp - __ bcax(v3, __ T16B, v7, v1, v27); // bcax v3.16B, v7.16B, v1.16B, v27.16B - __ eor3(v21, __ T16B, v18, v14, v8); // eor3 v21.16B, v18.16B, v14.16B, v8.16B - __ rax1(v18, __ T2D, v22, v25); // rax1 v18.2D, v22.2D, v25.2D - __ xar(v5, __ T2D, v20, v21, 37); // xar v5.2D, v20.2D, v21.2D, #37 + __ bcax(v13, __ T16B, v22, v11, v1); // bcax v13.16B, v22.16B, v11.16B, v1.16B + __ eor3(v13, __ T16B, v8, v20, v16); // eor3 v13.16B, v8.16B, v20.16B, v16.16B + __ rax1(v25, __ T2D, v15, v4); // rax1 v25.2D, v15.2D, v4.2D + __ xar(v4, __ T2D, v17, v8, 13); // xar v4.2D, v17.2D, v8.2D, #13 // SHA512SIMDOp - __ sha512h(v23, __ T2D, v16, v30); // sha512h q23, q16, v30.2D - __ sha512h2(v20, __ T2D, v20, v0); // sha512h2 q20, q20, v0.2D - __ sha512su0(v4, __ T2D, v19); // sha512su0 v4.2D, v19.2D - __ sha512su1(v24, __ T2D, v4, v20); // sha512su1 v24.2D, v4.2D, v20.2D + __ sha512h(v29, __ T2D, v4, v28); // sha512h q29, q4, v28.2D + __ sha512h2(v16, __ T2D, v29, v26); // sha512h2 q16, q29, v26.2D + __ sha512su0(v9, __ T2D, v14); // sha512su0 v9.2D, v14.2D + __ sha512su1(v2, __ T2D, v11, v28); // sha512su1 v2.2D, v11.2D, v28.2D // SVEBinaryImmOp - __ sve_add(z4, __ D, 210u); // add z4.d, z4.d, #0xd2 - __ sve_sub(z19, __ B, 71u); // sub z19.b, z19.b, #0x47 - __ sve_and(z8, __ H, 49663u); // and z8.h, z8.h, #0xc1ff - __ sve_eor(z31, __ S, 4294967231u); // eor z31.s, z31.s, #0xffffffbf - __ sve_orr(z1, __ H, 16368u); // orr z1.h, z1.h, #0x3ff0 + __ sve_add(z3, __ B, 10u); // add z3.b, z3.b, #0xa + __ sve_sub(z26, __ S, 150u); // sub z26.s, z26.s, #0x96 + __ sve_and(z14, __ H, 57343u); // and z14.h, z14.h, #0xdfff + __ sve_eor(z24, __ B, 191u); // eor z24.b, z24.b, #0xbf + __ sve_orr(z17, __ S, 4294966791u); // orr z17.s, z17.s, #0xfffffe07 // SVEBinaryImmOp - __ sve_add(z0, __ H, 61u); // add z0.h, z0.h, #0x3d - __ sve_sub(z24, __ S, 36u); // sub z24.s, z24.s, #0x24 - __ sve_and(z27, __ B, 243u); // and z27.b, z27.b, #0xf3 - __ sve_eor(z24, __ H, 65534u); // eor z24.h, z24.h, #0xfffe - __ sve_orr(z22, __ S, 4294967293u); // orr z22.s, z22.s, #0xfffffffd + __ sve_add(z20, __ S, 3u); // add z20.s, z20.s, #0x3 + __ sve_sub(z4, __ S, 196u); // sub z4.s, z4.s, #0xc4 + __ sve_and(z4, __ S, 4286578691u); // and z4.s, z4.s, #0xff800003 + __ sve_eor(z25, __ S, 33553408u); // eor z25.s, z25.s, #0x1fffc00 + __ sve_orr(z8, __ H, 49663u); // orr z8.h, z8.h, #0xc1ff // SVEBinaryImmOp - __ sve_add(z29, __ H, 113u); // add z29.h, z29.h, #0x71 - __ sve_sub(z20, __ B, 165u); // sub z20.b, z20.b, #0xa5 - __ sve_and(z28, __ H, 32256u); // and z28.h, z28.h, #0x7e00 - __ sve_eor(z12, __ S, 4287102855u); // eor z12.s, z12.s, #0xff87ff87 - __ sve_orr(z9, __ S, 3825205247u); // orr z9.s, z9.s, #0xe3ffffff + __ sve_add(z30, __ S, 36u); // add z30.s, z30.s, #0x24 + __ sve_sub(z30, __ B, 85u); // sub z30.b, z30.b, #0x55 + __ sve_and(z19, __ H, 4032u); // and z19.h, z19.h, #0xfc0 + __ sve_eor(z7, __ D, 274877904896u); // eor z7.d, z7.d, #0x3ffffff800 + __ sve_orr(z27, __ B, 243u); // orr z27.b, z27.b, #0xf3 // SVEBinaryImmOp - __ sve_add(z18, __ S, 41u); // add z18.s, z18.s, #0x29 - __ sve_sub(z0, __ B, 98u); // sub z0.b, z0.b, #0x62 - __ sve_and(z8, __ H, 32768u); // and z8.h, z8.h, #0x8000 - __ sve_eor(z4, __ H, 508u); // eor z4.h, z4.h, #0x1fc - __ sve_orr(z0, __ H, 64512u); // orr z0.h, z0.h, #0xfc00 + __ sve_add(z23, __ H, 132u); // add z23.h, z23.h, #0x84 + __ sve_sub(z30, __ S, 183u); // sub z30.s, z30.s, #0xb7 + __ sve_and(z20, __ D, 4503599627354112u); // and z20.d, z20.d, #0xfffffffffc000 + __ sve_eor(z13, __ S, 4042322160u); // eor z13.s, z13.s, #0xf0f0f0f0 + __ sve_orr(z28, __ H, 32256u); // orr z28.h, z28.h, #0x7e00 // SVEBinaryImmOp - __ sve_add(z3, __ B, 79u); // add z3.b, z3.b, #0x4f - __ sve_sub(z19, __ D, 84u); // sub z19.d, z19.d, #0x54 - __ sve_and(z24, __ B, 62u); // and z24.b, z24.b, #0x3e - __ sve_eor(z24, __ D, 18428729675200069887u); // eor z24.d, z24.d, #0xffc00000000000ff - __ sve_orr(z11, __ D, 17296056810822168583u); // orr z11.d, z11.d, #0xf007f007f007f007 + __ sve_add(z11, __ S, 13u); // add z11.s, z11.s, #0xd + __ sve_sub(z24, __ H, 159u); // sub z24.h, z24.h, #0x9f + __ sve_and(z13, __ S, 2151677951u); // and z13.s, z13.s, #0x803fffff + __ sve_eor(z4, __ B, 124u); // eor z4.b, z4.b, #0x7c + __ sve_orr(z7, __ H, 32768u); // orr z7.h, z7.h, #0x8000 // SVEBinaryImmOp - __ sve_add(z31, __ S, 115u); // add z31.s, z31.s, #0x73 - __ sve_sub(z3, __ D, 134u); // sub z3.d, z3.d, #0x86 - __ sve_and(z22, __ S, 4042322160u); // and z22.s, z22.s, #0xf0f0f0f0 - __ sve_eor(z3, __ B, 225u); // eor z3.b, z3.b, #0xe1 - __ sve_orr(z9, __ S, 4164941887u); // orr z9.s, z9.s, #0xf83ff83f + __ sve_add(z4, __ H, 243u); // add z4.h, z4.h, #0xf3 + __ sve_sub(z5, __ B, 86u); // sub z5.b, z5.b, #0x56 + __ sve_and(z21, __ D, 8064u); // and z21.d, z21.d, #0x1f80 + __ sve_eor(z9, __ S, 130023424u); // eor z9.s, z9.s, #0x7c00000 + __ sve_orr(z24, __ B, 62u); // orr z24.b, z24.b, #0x3e // SVEVectorOp - __ sve_add(z0, __ D, z4, z2); // add z0.d, z4.d, z2.d - __ sve_sub(z14, __ S, z6, z11); // sub z14.s, z6.s, z11.s - __ sve_fadd(z14, __ S, z17, z30); // fadd z14.s, z17.s, z30.s - __ sve_fmul(z3, __ S, z3, z23); // fmul z3.s, z3.s, z23.s - __ sve_fsub(z3, __ S, z24, z28); // fsub z3.s, z24.s, z28.s - __ sve_abs(z19, __ D, p5, z7); // abs z19.d, p5/m, z7.d - __ sve_add(z21, __ H, p3, z5); // add z21.h, p3/m, z21.h, z5.h - __ sve_and(z26, __ S, p1, z22); // and z26.s, p1/m, z26.s, z22.s - __ sve_asr(z17, __ H, p0, z3); // asr z17.h, p0/m, z17.h, z3.h - __ sve_bic(z20, __ H, p3, z8); // bic z20.h, p3/m, z20.h, z8.h - __ sve_clz(z14, __ H, p4, z17); // clz z14.h, p4/m, z17.h - __ sve_cnt(z13, __ D, p6, z18); // cnt z13.d, p6/m, z18.d - __ sve_eor(z19, __ H, p2, z16); // eor z19.h, p2/m, z19.h, z16.h - __ sve_lsl(z27, __ S, p5, z28); // lsl z27.s, p5/m, z27.s, z28.s - __ sve_lsr(z8, __ D, p2, z5); // lsr z8.d, p2/m, z8.d, z5.d - __ sve_mul(z28, __ H, p2, z0); // mul z28.h, p2/m, z28.h, z0.h - __ sve_neg(z25, __ B, p5, z21); // neg z25.b, p5/m, z21.b - __ sve_not(z3, __ B, p5, z26); // not z3.b, p5/m, z26.b - __ sve_orr(z26, __ S, p7, z19); // orr z26.s, p7/m, z26.s, z19.s - __ sve_rbit(z1, __ D, p3, z14); // rbit z1.d, p3/m, z14.d - __ sve_revb(z14, __ H, p0, z18); // revb z14.h, p0/m, z18.h - __ sve_smax(z31, __ S, p5, z23); // smax z31.s, p5/m, z31.s, z23.s - __ sve_smin(z30, __ B, p3, z8); // smin z30.b, p3/m, z30.b, z8.b - __ sve_sub(z0, __ S, p3, z23); // sub z0.s, p3/m, z0.s, z23.s - __ sve_fabs(z0, __ D, p4, z26); // fabs z0.d, p4/m, z26.d - __ sve_fadd(z24, __ D, p3, z22); // fadd z24.d, p3/m, z24.d, z22.d - __ sve_fdiv(z2, __ D, p0, z11); // fdiv z2.d, p0/m, z2.d, z11.d - __ sve_fmax(z12, __ D, p5, z24); // fmax z12.d, p5/m, z12.d, z24.d - __ sve_fmin(z9, __ D, p7, z17); // fmin z9.d, p7/m, z9.d, z17.d - __ sve_fmul(z20, __ D, p5, z4); // fmul z20.d, p5/m, z20.d, z4.d - __ sve_fneg(z13, __ D, p7, z22); // fneg z13.d, p7/m, z22.d - __ sve_frintm(z31, __ D, p6, z18); // frintm z31.d, p6/m, z18.d - __ sve_frintn(z15, __ D, p2, z13); // frintn z15.d, p2/m, z13.d - __ sve_frintp(z20, __ S, p1, z1); // frintp z20.s, p1/m, z1.s - __ sve_fsqrt(z14, __ S, p0, z7); // fsqrt z14.s, p0/m, z7.s - __ sve_fsub(z12, __ D, p4, z4); // fsub z12.d, p4/m, z12.d, z4.d - __ sve_fmad(z15, __ S, p0, z3, z30); // fmad z15.s, p0/m, z3.s, z30.s - __ sve_fmla(z20, __ D, p1, z20, z31); // fmla z20.d, p1/m, z20.d, z31.d - __ sve_fmls(z13, __ D, p3, z9, z14); // fmls z13.d, p3/m, z9.d, z14.d - __ sve_fmsb(z1, __ S, p3, z28, z3); // fmsb z1.s, p3/m, z28.s, z3.s - __ sve_fnmad(z26, __ S, p2, z25, z9); // fnmad z26.s, p2/m, z25.s, z9.s - __ sve_fnmsb(z26, __ D, p2, z14, z1); // fnmsb z26.d, p2/m, z14.d, z1.d - __ sve_fnmla(z26, __ D, p1, z29, z20); // fnmla z26.d, p1/m, z29.d, z20.d - __ sve_fnmls(z6, __ D, p7, z13, z1); // fnmls z6.d, p7/m, z13.d, z1.d - __ sve_mla(z11, __ B, p2, z1, z1); // mla z11.b, p2/m, z1.b, z1.b - __ sve_mls(z27, __ B, p6, z15, z2); // mls z27.b, p6/m, z15.b, z2.b - __ sve_and(z30, z17, z25); // and z30.d, z17.d, z25.d - __ sve_eor(z2, z24, z3); // eor z2.d, z24.d, z3.d - __ sve_orr(z29, z13, z3); // orr z29.d, z13.d, z3.d - __ sve_bic(z14, z16, z28); // bic z14.d, z16.d, z28.d - __ sve_uzp1(z4, __ S, z11, z27); // uzp1 z4.s, z11.s, z27.s - __ sve_uzp2(z2, __ D, z16, z1); // uzp2 z2.d, z16.d, z1.d - __ sve_fabd(z7, __ D, p5, z31); // fabd z7.d, p5/m, z7.d, z31.d - __ sve_bext(z16, __ S, z10, z22); // bext z16.s, z10.s, z22.s - __ sve_bdep(z29, __ B, z7, z22); // bdep z29.b, z7.b, z22.b - __ sve_eor3(z12, z24, z11); // eor3 z12.d, z12.d, z24.d, z11.d + __ sve_add(z23, __ S, z28, z13); // add z23.s, z28.s, z13.s + __ sve_sub(z10, __ S, z26, z12); // sub z10.s, z26.s, z12.s + __ sve_fadd(z30, __ S, z17, z14); // fadd z30.s, z17.s, z14.s + __ sve_fmul(z29, __ D, z16, z21); // fmul z29.d, z16.d, z21.d + __ sve_fsub(z7, __ S, z19, z2); // fsub z7.s, z19.s, z2.s + __ sve_abs(z26, __ S, p4, z9); // abs z26.s, p4/m, z9.s + __ sve_add(z17, __ B, p5, z0); // add z17.b, p5/m, z17.b, z0.b + __ sve_and(z2, __ B, p6, z14); // and z2.b, p6/m, z2.b, z14.b + __ sve_asr(z11, __ S, p5, z14); // asr z11.s, p5/m, z11.s, z14.s + __ sve_bic(z29, __ B, p3, z3); // bic z29.b, p3/m, z29.b, z3.b + __ sve_clz(z22, __ D, p2, z3); // clz z22.d, p2/m, z3.d + __ sve_cnt(z27, __ S, p0, z19); // cnt z27.s, p0/m, z19.s + __ sve_eor(z7, __ H, p6, z21); // eor z7.h, p6/m, z7.h, z21.h + __ sve_lsl(z5, __ B, p2, z25); // lsl z5.b, p2/m, z5.b, z25.b + __ sve_lsr(z21, __ B, p4, z17); // lsr z21.b, p4/m, z21.b, z17.b + __ sve_mul(z3, __ H, p2, z19); // mul z3.h, p2/m, z3.h, z19.h + __ sve_neg(z7, __ S, p3, z14); // neg z7.s, p3/m, z14.s + __ sve_not(z17, __ D, p2, z13); // not z17.d, p2/m, z13.d + __ sve_orr(z17, __ H, p7, z17); // orr z17.h, p7/m, z17.h, z17.h + __ sve_rbit(z15, __ S, p3, z26); // rbit z15.s, p3/m, z26.s + __ sve_revb(z27, __ H, p5, z7); // revb z27.h, p5/m, z7.h + __ sve_smax(z5, __ H, p7, z27); // smax z5.h, p7/m, z5.h, z27.h + __ sve_smin(z0, __ S, p3, z24); // smin z0.s, p3/m, z0.s, z24.s + __ sve_sub(z20, __ S, p0, z3); // sub z20.s, p0/m, z20.s, z3.s + __ sve_fabs(z25, __ D, p1, z25); // fabs z25.d, p1/m, z25.d + __ sve_fadd(z17, __ S, p4, z1); // fadd z17.s, p4/m, z17.s, z1.s + __ sve_fdiv(z14, __ S, p7, z13); // fdiv z14.s, p7/m, z14.s, z13.s + __ sve_fmax(z17, __ D, p0, z30); // fmax z17.d, p0/m, z17.d, z30.d + __ sve_fmin(z22, __ S, p5, z29); // fmin z22.s, p5/m, z22.s, z29.s + __ sve_fmul(z8, __ S, p0, z0); // fmul z8.s, p0/m, z8.s, z0.s + __ sve_fneg(z23, __ D, p5, z0); // fneg z23.d, p5/m, z0.d + __ sve_frintm(z25, __ S, p6, z23); // frintm z25.s, p6/m, z23.s + __ sve_frintn(z21, __ S, p5, z1); // frintn z21.s, p5/m, z1.s + __ sve_frintp(z10, __ D, p5, z11); // frintp z10.d, p5/m, z11.d + __ sve_fsqrt(z23, __ D, p6, z8); // fsqrt z23.d, p6/m, z8.d + __ sve_fsub(z17, __ D, p5, z19); // fsub z17.d, p5/m, z17.d, z19.d + __ sve_fmad(z4, __ D, p5, z13, z30); // fmad z4.d, p5/m, z13.d, z30.d + __ sve_fmla(z30, __ D, p7, z25, z17); // fmla z30.d, p7/m, z25.d, z17.d + __ sve_fmls(z14, __ D, p2, z12, z28); // fmls z14.d, p2/m, z12.d, z28.d + __ sve_fmsb(z5, __ S, p0, z13, z13); // fmsb z5.s, p0/m, z13.s, z13.s + __ sve_fnmad(z7, __ S, p2, z11, z19); // fnmad z7.s, p2/m, z11.s, z19.s + __ sve_fnmsb(z25, __ D, p3, z2, z3); // fnmsb z25.d, p3/m, z2.d, z3.d + __ sve_fnmla(z0, __ D, p5, z5, z20); // fnmla z0.d, p5/m, z5.d, z20.d + __ sve_fnmls(z28, __ S, p3, z13, z8); // fnmls z28.s, p3/m, z13.s, z8.s + __ sve_mla(z29, __ B, p0, z14, z27); // mla z29.b, p0/m, z14.b, z27.b + __ sve_mls(z3, __ H, p6, z8, z24); // mls z3.h, p6/m, z8.h, z24.h + __ sve_and(z1, z25, z10); // and z1.d, z25.d, z10.d + __ sve_eor(z1, z20, z25); // eor z1.d, z20.d, z25.d + __ sve_orr(z28, z19, z16); // orr z28.d, z19.d, z16.d + __ sve_bic(z27, z13, z1); // bic z27.d, z13.d, z1.d + __ sve_uzp1(z11, __ B, z9, z1); // uzp1 z11.b, z9.b, z1.b + __ sve_uzp2(z1, __ H, z27, z26); // uzp2 z1.h, z27.h, z26.h + __ sve_fabd(z2, __ D, p1, z29); // fabd z2.d, p1/m, z2.d, z29.d + __ sve_bext(z24, __ D, z2, z2); // bext z24.d, z2.d, z2.d + __ sve_bdep(z3, __ H, z25, z28); // bdep z3.h, z25.h, z28.h + __ sve_eor3(z3, z22, z13); // eor3 z3.d, z3.d, z22.d, z13.d // SVEReductionOp - __ sve_andv(v11, __ B, p2, z0); // andv b11, p2, z0.b - __ sve_orv(v23, __ B, p5, z20); // orv b23, p5, z20.b - __ sve_eorv(v3, __ B, p3, z15); // eorv b3, p3, z15.b - __ sve_smaxv(v30, __ B, p6, z27); // smaxv b30, p6, z27.b - __ sve_sminv(v21, __ D, p6, z10); // sminv d21, p6, z10.d - __ sve_fminv(v3, __ S, p6, z4); // fminv s3, p6, z4.s - __ sve_fmaxv(v6, __ S, p0, z21); // fmaxv s6, p0, z21.s - __ sve_fadda(v25, __ D, p6, z30); // fadda d25, p6, d25, z30.d - __ sve_uaddv(v31, __ H, p4, z1); // uaddv d31, p4, z1.h - -// AddWideNEONOp - __ saddwv(v12, v13, __ T8H, v14, __ T8B); // saddw v12.8H, v13.8H, v14.8B - __ saddwv2(v30, v31, __ T8H, v0, __ T16B); // saddw2 v30.8H, v31.8H, v0.16B - __ saddwv(v13, v14, __ T4S, v15, __ T4H); // saddw v13.4S, v14.4S, v15.4H - __ saddwv2(v8, v9, __ T4S, v10, __ T8H); // saddw2 v8.4S, v9.4S, v10.8H - __ saddwv(v25, v26, __ T2D, v27, __ T2S); // saddw v25.2D, v26.2D, v27.2S - __ saddwv2(v29, v30, __ T2D, v31, __ T4S); // saddw2 v29.2D, v30.2D, v31.4S - __ uaddwv(v1, v2, __ T8H, v3, __ T8B); // uaddw v1.8H, v2.8H, v3.8B - __ uaddwv2(v31, v0, __ T8H, v1, __ T16B); // uaddw2 v31.8H, v0.8H, v1.16B - __ uaddwv(v23, v24, __ T4S, v25, __ T4H); // uaddw v23.4S, v24.4S, v25.4H - __ uaddwv2(v31, v0, __ T4S, v1, __ T8H); // uaddw2 v31.4S, v0.4S, v1.8H - __ uaddwv(v20, v21, __ T2D, v22, __ T2S); // uaddw v20.2D, v21.2D, v22.2S - __ uaddwv2(v0, v1, __ T2D, v2, __ T4S); // uaddw2 v0.2D, v1.2D, v2.4S + __ sve_andv(v27, __ H, p4, z4); // andv h27, p4, z4.h + __ sve_orv(v26, __ S, p4, z2); // orv s26, p4, z2.s + __ sve_eorv(v1, __ S, p7, z7); // eorv s1, p7, z7.s + __ sve_smaxv(v30, __ H, p7, z16); // smaxv h30, p7, z16.h + __ sve_sminv(v21, __ B, p4, z28); // sminv b21, p4, z28.b + __ sve_fminv(v21, __ D, p1, z12); // fminv d21, p1, z12.d + __ sve_fmaxv(v11, __ S, p2, z10); // fmaxv s11, p2, z10.s + __ sve_fadda(v0, __ D, p1, z22); // fadda d0, p1, d0, z22.d + __ sve_uaddv(v20, __ H, p1, z3); // uaddv d20, p1, z3.h __ bind(forth); @@ -1327,30 +1298,30 @@ 0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061, 0x120cb166, 0x321764bc, 0x52174681, 0x720c0227, 0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01, - 0x14000000, 0x17ffffd7, 0x14000441, 0x94000000, - 0x97ffffd4, 0x9400043e, 0x3400000a, 0x34fffa2a, - 0x3400876a, 0x35000008, 0x35fff9c8, 0x35008708, - 0xb400000b, 0xb4fff96b, 0xb40086ab, 0xb500001d, - 0xb5fff91d, 0xb500865d, 0x10000013, 0x10fff8b3, - 0x100085f3, 0x90000013, 0x36300016, 0x3637f836, - 0x36308576, 0x3758000c, 0x375ff7cc, 0x3758850c, + 0x14000000, 0x17ffffd7, 0x14000428, 0x94000000, + 0x97ffffd4, 0x94000425, 0x3400000a, 0x34fffa2a, + 0x3400844a, 0x35000008, 0x35fff9c8, 0x350083e8, + 0xb400000b, 0xb4fff96b, 0xb400838b, 0xb500001d, + 0xb5fff91d, 0xb500833d, 0x10000013, 0x10fff8b3, + 0x100082d3, 0x90000013, 0x36300016, 0x3637f836, + 0x36308256, 0x3758000c, 0x375ff7cc, 0x375881ec, 0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc, 0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f, 0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016, 0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0, - 0x540082e0, 0x54000001, 0x54fff541, 0x54008281, - 0x54000002, 0x54fff4e2, 0x54008222, 0x54000002, - 0x54fff482, 0x540081c2, 0x54000003, 0x54fff423, - 0x54008163, 0x54000003, 0x54fff3c3, 0x54008103, - 0x54000004, 0x54fff364, 0x540080a4, 0x54000005, - 0x54fff305, 0x54008045, 0x54000006, 0x54fff2a6, - 0x54007fe6, 0x54000007, 0x54fff247, 0x54007f87, - 0x54000008, 0x54fff1e8, 0x54007f28, 0x54000009, - 0x54fff189, 0x54007ec9, 0x5400000a, 0x54fff12a, - 0x54007e6a, 0x5400000b, 0x54fff0cb, 0x54007e0b, - 0x5400000c, 0x54fff06c, 0x54007dac, 0x5400000d, - 0x54fff00d, 0x54007d4d, 0x5400000e, 0x54ffefae, - 0x54007cee, 0x5400000f, 0x54ffef4f, 0x54007c8f, + 0x54007fc0, 0x54000001, 0x54fff541, 0x54007f61, + 0x54000002, 0x54fff4e2, 0x54007f02, 0x54000002, + 0x54fff482, 0x54007ea2, 0x54000003, 0x54fff423, + 0x54007e43, 0x54000003, 0x54fff3c3, 0x54007de3, + 0x54000004, 0x54fff364, 0x54007d84, 0x54000005, + 0x54fff305, 0x54007d25, 0x54000006, 0x54fff2a6, + 0x54007cc6, 0x54000007, 0x54fff247, 0x54007c67, + 0x54000008, 0x54fff1e8, 0x54007c08, 0x54000009, + 0x54fff189, 0x54007ba9, 0x5400000a, 0x54fff12a, + 0x54007b4a, 0x5400000b, 0x54fff0cb, 0x54007aeb, + 0x5400000c, 0x54fff06c, 0x54007a8c, 0x5400000d, + 0x54fff00d, 0x54007a2d, 0x5400000e, 0x54ffefae, + 0x540079ce, 0x5400000f, 0x54ffef4f, 0x5400796f, 0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60, 0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f, 0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf, @@ -1375,23 +1346,23 @@ 0xb81b1022, 0x381ea354, 0x79002fd7, 0xf85cf39a, 0xb8580309, 0x385e218c, 0x784051e1, 0x389e11d8, 0x789fa1f8, 0x79c01865, 0xb881131b, 0xfc5dd3ad, - 0xbc5d1137, 0xfc00900b, 0xbc181015, 0xf818ec7d, + 0xbc5d1136, 0xfc00900b, 0xbc181014, 0xf818ec7d, 0xb81b8c91, 0x381efc40, 0x78007c3d, 0xf857beb0, 0xb8413dd4, 0x385fddd6, 0x78409e2f, 0x389eddea, 0x789e7d94, 0x78de3d55, 0xb8805c13, 0xfc5cadc0, - 0xbc428c23, 0xfc1a2dc4, 0xbc1caf92, 0xf81475f6, + 0xbc428c23, 0xfc1a2dc4, 0xbc1caf91, 0xf81475f6, 0xb81f95d1, 0x381e757e, 0x78014561, 0xf8402436, 0xb85896e2, 0x385f4763, 0x785db4f0, 0x3880374f, 0x789e25e7, 0x78dd0563, 0xb88166f9, 0xfc529540, - 0xbc4374d3, 0xfc1166ae, 0xbc1ba6c0, 0xf820ea7b, + 0xbc4374d1, 0xfc1166ad, 0xbc1ba6c0, 0xf820ea7b, 0xb82d68c8, 0x38367a04, 0x782f4b59, 0xf878c8a4, 0xb8674a24, 0x386b78f1, 0x78776bc0, 0x38a15aca, - 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, 0xfc6ecbbe, - 0xbc65d8a8, 0xfc2de919, 0xbc3a7b11, 0xf91f1193, + 0x78bedbd5, 0x78fcd94b, 0xb8aa4a7c, 0xfc6ecbbd, + 0xbc65d8a8, 0xfc2de918, 0xbc3a7b11, 0xf91f1193, 0xb91ed5f7, 0x391ec9bd, 0x79182ceb, 0xf95d4b0a, 0xb9581010, 0x395fc034, 0x795fb221, 0x399d8731, 0x799efb3b, 0x79dd1a2e, 0xb998e4ea, 0xfd583723, - 0xbd5ea12c, 0xfd18dc38, 0xbd1b0e83, 0x58ffdaa2, + 0xbd5ea12c, 0xfd18dc37, 0xbd1b0e83, 0x58ffdaa2, 0x1800001d, 0xf885d1c0, 0xd8ffda40, 0xf8a77820, 0xf9980220, 0x1a030301, 0x3a140311, 0x5a0d000b, 0x7a07015c, 0x9a1001e4, 0xba140182, 0xda0d01bd, @@ -1412,193 +1383,187 @@ 0x9ad521f7, 0x9adb263c, 0x9ac0286a, 0x9ac92f27, 0x9bdd7de6, 0x9b427d4f, 0x1b0b2cf1, 0x1b1ddcf7, 0x9b0b2f6e, 0x9b0cbf04, 0x9b2b728e, 0x9b2cdd6d, - 0x9bae275e, 0x9ba7954d, 0x7ea3d5fe, 0x1e30098c, - 0x1e321bff, 0x1e302ab3, 0x1e35394f, 0x7efcd542, - 0x1e7f0bc7, 0x1e621832, 0x1e632946, 0x1e673979, - 0x1f000d81, 0x1f06dfb3, 0x1f3c6c06, 0x1f2774a2, - 0x1f4d332c, 0x1f48ca78, 0x1f755356, 0x1f7e5853, - 0x1e2042c8, 0x1e20c2b3, 0x1e21424c, 0x1e21c0d5, - 0x1e22c070, 0x1e23c3a3, 0x1ee24383, 0x1e6041cf, - 0x1e60c1aa, 0x1e61424c, 0x1e61c34a, 0x1e6240e7, - 0x1e3803ae, 0x9e3802e0, 0x1e780180, 0x9e7801d7, - 0x1e2200ed, 0x9e2200ef, 0x1e620289, 0x9e620393, - 0x1e24021e, 0x9e640122, 0x1e3002b0, 0x9e70009d, - 0x1e260361, 0x9e660318, 0x1e2702ae, 0x9e6700ad, - 0x1e392180, 0x1e7e2320, 0x1e202388, 0x1e6022a8, + 0x9bae275e, 0x9ba7954d, 0x7ea3d5fd, 0x1e2f098b, + 0x1e311bde, 0x1e2f2a93, 0x1e35392f, 0x7efbd522, + 0x1e7e0ba7, 0x1e621831, 0x1e632946, 0x1e673978, + 0x1f000d61, 0x1f06db91, 0x1f3b6806, 0x1f2770a2, + 0x1f4d2f2b, 0x1f48c677, 0x1f744f35, 0x1f7d5851, + 0x1e2042a8, 0x1e20c293, 0x1e21422b, 0x1e21c0d4, + 0x1e22c06f, 0x1e23c383, 0x1ee24363, 0x1e6041ce, + 0x1e60c18a, 0x1e61422b, 0x1e61c32a, 0x1e6240e7, + 0x1e38038e, 0x9e3802c0, 0x1e780180, 0x9e7801b7, + 0x1e2200ed, 0x9e2200ee, 0x1e620288, 0x9e620391, + 0x1e24021e, 0x9e640122, 0x1e300290, 0x9e70009d, + 0x1e260341, 0x9e6602f8, 0x1e2702ae, 0x9e6700ac, + 0x1e382180, 0x1e7d2300, 0x1e202368, 0x1e6022a8, 0x293a1796, 0x29426e73, 0x697c68fc, 0xa93d0486, 0xa97b5eba, 0x29b47934, 0x29c2534d, 0x69f62dbd, 0xa9bd54bb, 0xa9c503c6, 0x28a63e13, 0x28e25d2c, 0x68c469e0, 0xa8b34748, 0xa8f51c59, 0x28264433, 0x285036c0, 0xa8005f7d, 0xa872290b, 0x0c407160, - 0x4cdfa350, 0x0cd16f56, 0x4cdf27bb, 0x0d40c0d6, - 0x4ddfcbae, 0x0dd0cd96, 0x4c408c01, 0x0cdf86aa, - 0x4d60c327, 0x0dffc929, 0x4deecd89, 0x4cd14887, - 0x0c404a37, 0x4d40e6c4, 0x4ddfe84d, 0x0dcced50, - 0x4cdf0444, 0x0ccb0286, 0x0d60e18c, 0x0dffe630, - 0x0df0eb2e, 0x0e31bab4, 0x4e31b841, 0x0e71bb17, + 0x4cdfa350, 0x0cd16f55, 0x4cdf27ba, 0x0d40c0d5, + 0x4ddfcbad, 0x0dd0cd95, 0x4c408c01, 0x0cdf86a9, + 0x4d60c327, 0x0dffc928, 0x4deecd89, 0x4cd14887, + 0x0c404a37, 0x4d40e6c3, 0x4ddfe84c, 0x0dcced4f, + 0x4cdf0444, 0x0ccb0286, 0x0d60e18b, 0x0dffe62f, + 0x0df0eb2e, 0x0e31bab4, 0x4e31b841, 0x0e71baf6, 0x4e71bbfe, 0x4eb1b9ee, 0x0e30a862, 0x4e30a8e6, - 0x0e70a883, 0x4e70a928, 0x4eb0ab59, 0x6e30f820, - 0x0e31ab9b, 0x2e31abfe, 0x4e31a8c5, 0x6e31a8c5, - 0x0e71abfe, 0x2e71a98b, 0x4e71ab59, 0x6e71a820, - 0x4eb1a81f, 0x6eb1a820, 0x6eb0fa93, 0x7e30fbdd, - 0x7e70fb7a, 0x7eb0f949, 0x7ef0fb7a, 0x0ea0c9ac, - 0x4ea0ca0f, 0x4ee0c98b, 0x2ea0c98b, 0x6ea0ca72, - 0x6ee0cb59, 0x0ea0daf6, 0x4ea0db38, 0x4ee0d820, - 0x0ea0ea51, 0x4ea0e98b, 0x4ee0e8e6, 0x2ea0dbdd, - 0x6ea0d8e6, 0x6ee0d8c5, 0x0e20b8c5, 0x4e20bad5, - 0x0e60ba93, 0x4e60ba30, 0x0ea0ba72, 0x4ea0bbfe, - 0x4ee0bb9b, 0x0ea0fbbc, 0x4ea0f841, 0x4ee0fbbc, - 0x2ea0f841, 0x6ea0fab4, 0x6ee0fbdd, 0x2ea1fa30, - 0x6ea1f9cd, 0x6ee1f96a, 0x2e205bdd, 0x6e205bdd, + 0x0e70a883, 0x4e70a907, 0x4eb0ab38, 0x6e30f820, + 0x0e31ab9b, 0x2e31abdd, 0x4e31a8c5, 0x6e31a8c5, + 0x0e71abdd, 0x2e71a98b, 0x4e71ab59, 0x6e71a820, + 0x4eb1abfe, 0x6eb1a820, 0x6eb0fa51, 0x7e30fbbc, + 0x7e70fb59, 0x7eb0f949, 0x7ef0fb59, 0x0ea0c9ac, + 0x4ea0ca0f, 0x4ee0c98b, 0x2ea0c96a, 0x6ea0ca51, + 0x6ee0cb38, 0x0ea0dad5, 0x4ea0db17, 0x4ee0d820, + 0x0ea0ea30, 0x4ea0e96a, 0x4ee0e8e6, 0x2ea0dbbc, + 0x6ea0d8e6, 0x6ee0d8c5, 0x0e20b8c5, 0x4e20bab4, + 0x0e60ba51, 0x4e60ba0f, 0x0ea0ba51, 0x4ea0bbdd, + 0x4ee0bb7a, 0x0ea0fbbc, 0x4ea0f841, 0x4ee0fb9b, + 0x2ea0f820, 0x6ea0fab4, 0x6ee0fbbc, 0x2ea1fa0f, + 0x6ea1f9ac, 0x6ee1f96a, 0x2e205bbc, 0x6e205bbc, 0x0e351e93, 0x4e381ef6, 0x0eac1d6a, 0x4ea61ca4, - 0x2e211c1f, 0x6e371ed5, 0x0e2a8528, 0x4e21841f, - 0x0e758693, 0x4e6c856a, 0x0ebe87bc, 0x4ea48462, - 0x4efb8759, 0x0e27d4c5, 0x4e25d483, 0x4e6ad528, - 0x2e3886f6, 0x6e358693, 0x2e6f85cd, 0x6e6784c5, - 0x2ebf87dd, 0x6eba8738, 0x6ef786d5, 0x0ebcd77a, - 0x4ebad738, 0x4ee5d483, 0x0e3a9f38, 0x4e3c9f7a, - 0x0e799f17, 0x4e719e0f, 0x0eb79ed5, 0x4ea59c83, - 0x2ebad738, 0x6eaad528, 0x6efbd759, 0x2e36d6b4, - 0x6e32d630, 0x6e73d651, 0x2e24dc62, 0x6e23dc41, + 0x2e201ffe, 0x6e361eb4, 0x0e2a8528, 0x4e2087fe, + 0x0e738651, 0x4e6c856a, 0x0ebd879b, 0x4ea48462, + 0x4efa8738, 0x0e26d4a4, 0x4e25d483, 0x4e6ad528, + 0x2e3886f6, 0x6e338651, 0x2e6f85cd, 0x6e6684a4, + 0x2ebe87bc, 0x6eb98717, 0x6ef786d5, 0x0ebbd759, + 0x4ebad738, 0x4ee5d483, 0x0e399f17, 0x4e3c9f7a, + 0x0e799f17, 0x4e709dee, 0x0eb79ed5, 0x4ea59c83, + 0x2eb9d717, 0x6eaad528, 0x6efad738, 0x2e35d693, + 0x6e31d60f, 0x6e72d630, 0x2e24dc62, 0x6e23dc41, 0x6e62dc20, 0x0e7a9738, 0x4e6694a4, 0x0ea59483, - 0x4eae95ac, 0x0e21cc1f, 0x4e3ecfbc, 0x4e6ccd6a, - 0x2e7c977a, 0x6e649462, 0x2eae95ac, 0x6eb49672, - 0x0ea1cc1f, 0x4ea3cc41, 0x4eefcdcd, 0x2e3fffdd, - 0x6e22fc20, 0x6e75fe93, 0x0e2e65ac, 0x4e336651, - 0x0e7866f6, 0x4e6f65cd, 0x0ebe67bc, 0x4ea067fe, - 0x0e21a41f, 0x4e23a441, 0x0e7ca77a, 0x4e7ea7bc, - 0x0ea6a4a4, 0x4ea0a7fe, 0x0e26f4a4, 0x4e28f4e6, - 0x4e60f7fe, 0x0e3c6f7a, 0x4e346e72, 0x0e6b6d49, - 0x4e6a6d28, 0x0eae6dac, 0x4ea26c20, 0x0e36aeb4, - 0x4e23ac41, 0x0e7aaf38, 0x4e64ac62, 0x0ea2ac20, - 0x4eabad49, 0x0ebaf738, 0x4ebcf77a, 0x4ef2f630, - 0x2ea0effe, 0x6ea5ec83, 0x6eeced6a, 0x0fa710c5, - 0x4f8b8149, 0x4fc710c5, 0x0f8750c5, 0x4faa8128, - 0x4fc750c5, 0x2f8890e6, 0x4fa880e6, 0x6fc59083, - 0x0f6f81cd, 0x4f448862, 0x0f848062, 0x4fab8149, - 0x0e3736d5, 0x4e323630, 0x0e743672, 0x4e6d358b, - 0x0eb736d5, 0x4eb93717, 0x4eee35ac, 0x0e3c3f7a, - 0x4e393f17, 0x0e7e3fbc, 0x4e703dee, 0x0ead3d8b, - 0x4eba3f38, 0x4ee33c41, 0x2e2e8dac, 0x6e218c1f, - 0x2e6c8d6a, 0x6e728e30, 0x2ea98d07, 0x6ea48c62, - 0x6ee58c83, 0x2e2f35cd, 0x6e353693, 0x2e733651, - 0x6e723630, 0x2ea53483, 0x6ea33441, 0x6eed358b, - 0x2e203ffe, 0x6e273cc5, 0x2e6a3d28, 0x6e713e0f, - 0x2ebf3fdd, 0x6ea03ffe, 0x6ee23c20, 0x0e36e6b4, - 0x4e29e507, 0x4e76e6b4, 0x2eb9e717, 0x6ebee7bc, - 0x6ef7e6d5, 0x2e3de79b, 0x6e3be759, 0x6e67e4c5, - 0x65d23ee0, 0x65903d92, 0x65d03fa7, 0x65912fe9, - 0x65d13bf9, 0x65932a0a, 0x25cb90c4, 0x25040bde, - 0x25c11085, 0x25c62c6b, 0x259f2279, 0x259d8993, - 0x24e5102b, 0x24ad5458, 0x24ec7ab5, 0x24387c6d, - 0xba5fd3e3, 0x3a5f03e5, 0xfa411be4, 0x7a42cbe2, - 0x93df03ff, 0xc820ffff, 0x8822fc7f, 0xc8247cbf, - 0x88267fff, 0x4e010fe0, 0x5e040420, 0x4e081fe1, - 0x4e0c1fe1, 0x4e0a1fe1, 0x4e071fe1, 0x4e042c20, - 0x4e062c20, 0x4e052c20, 0x4e083c20, 0x0e0c3c20, - 0x0e0a3c20, 0x0e073c20, 0x9eae0020, 0x0f03f409, - 0x6f03f40e, 0x4cc0ac3f, 0x0ea1b820, 0x4e21c862, - 0x4e61b8a4, 0x05a08020, 0x05104fe0, 0x05505001, - 0x05906fe2, 0x05d03005, 0x05101fea, 0x05901feb, - 0x04b0e3e0, 0x0470e7e1, 0x042f9c20, 0x043f9c35, - 0x047f9c20, 0x04ff9c20, 0x04299420, 0x04319160, - 0x0461943e, 0x04a19020, 0x04038100, 0x040381a0, - 0x040387e1, 0x04438be2, 0x04c38fe3, 0x040181e0, - 0x04018100, 0x04018621, 0x04418b22, 0x04418822, - 0x04818c23, 0x040081e0, 0x04008120, 0x04008761, - 0x04008621, 0x04408822, 0x04808c23, 0x042053ff, - 0x047f5401, 0x25208028, 0x2538cfe0, 0x2578d001, - 0x25b8efe2, 0x25f8f007, 0x2538dfea, 0x25b8dfeb, - 0xa400a3e0, 0xa420a7e0, 0xa4484be0, 0xa467afe0, - 0xa4a8a7ea, 0xa547a814, 0xa4084ffe, 0xa55c53e0, - 0xa5e1540b, 0xe400fbf6, 0xe408ffff, 0xe420e7e0, - 0xe4484be0, 0xe460efe0, 0xe547e400, 0xe4014be0, - 0xe4a84fe0, 0xe5f15000, 0x858043e0, 0x85a043ff, - 0xe59f5d08, 0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, - 0x04e0e3ec, 0x25104042, 0x25104871, 0x25904861, - 0x25904c92, 0x05344020, 0x05744041, 0x05b44062, - 0x05f44083, 0x252c8840, 0x253c1420, 0x25681572, - 0x25a21ce3, 0x25ea1e34, 0x253c0421, 0x25680572, - 0x25a20ce3, 0x25ea0e34, 0x0522c020, 0x05e6c0a4, - 0x2401a001, 0x2443a051, 0x24858881, 0x24c78cd1, - 0x24850891, 0x24c70cc1, 0x250f9001, 0x25508051, - 0x25802491, 0x25df28c1, 0x25850c81, 0x251e10d1, - 0x65816001, 0x65c36051, 0x65854891, 0x65c74cc1, - 0x05733820, 0x05b238a4, 0x05f138e6, 0x0570396a, - 0x65d0a001, 0x65d6a443, 0x65d4a826, 0x6594ac26, - 0x6554ac26, 0x6556ac26, 0x6552ac26, 0x65cbac85, - 0x65caac01, 0x6589ac85, 0x6588ac01, 0x65c9ac85, - 0x65c8ac01, 0x65dea833, 0x659ca509, 0x65d8a801, - 0x65dcac01, 0x655cb241, 0x0520a1e0, 0x0521a601, - 0x052281e0, 0x05238601, 0x04a14026, 0x042244a6, - 0x046344a6, 0x04a444a6, 0x04e544a7, 0x0568aca7, - 0x05b23230, 0x853040af, 0xc5b040af, 0xe57080af, - 0xe5b080af, 0x25034440, 0x254054c4, 0x25034640, - 0x25415a05, 0x25834440, 0x25c54489, 0x250b5d3a, - 0x2550dc20, 0x2518e3e1, 0x2518e021, 0x2518e0a1, - 0x2518e121, 0x2518e1a1, 0x2558e3e2, 0x2558e042, - 0x2558e0c2, 0x2558e142, 0x2598e3e3, 0x2598e063, - 0x2598e0e3, 0x2598e163, 0x25d8e3e4, 0x25d8e084, - 0x25d8e104, 0x25d8e184, 0x2518e407, 0x05214800, - 0x05614800, 0x05a14800, 0x05e14800, 0x05214c00, - 0x05614c00, 0x05a14c00, 0x05e14c00, 0x05304001, - 0x05314001, 0x05a18610, 0x05e18610, 0x05271e11, - 0x6545e891, 0x6585e891, 0x65c5e891, 0x6545c891, - 0x6585c891, 0x65c5c891, 0x45b0c210, 0x45f1c231, - 0x1e601000, 0x1e603000, 0x1e621000, 0x1e623000, - 0x1e641000, 0x1e643000, 0x1e661000, 0x1e663000, - 0x1e681000, 0x1e683000, 0x1e6a1000, 0x1e6a3000, - 0x1e6c1000, 0x1e6c3000, 0x1e6e1000, 0x1e6e3000, - 0x1e701000, 0x1e703000, 0x1e721000, 0x1e723000, - 0x1e741000, 0x1e743000, 0x1e761000, 0x1e763000, - 0x1e781000, 0x1e783000, 0x1e7a1000, 0x1e7a3000, - 0x1e7c1000, 0x1e7c3000, 0x1e7e1000, 0x1e7e3000, - 0xf8338131, 0xf83c01fb, 0xf82712f5, 0xf83f2059, - 0xf83f31fb, 0xf82a5277, 0xf8234010, 0xf83972fa, - 0xf8226190, 0xf8a483dc, 0xf8bd0370, 0xf8a613a9, - 0xf8b02087, 0xf8a7312f, 0xf8b75048, 0xf8bc43f5, - 0xf8a5701b, 0xf8b1608f, 0xf8fa8388, 0xf8f6037b, - 0xf8f91017, 0xf8e421e6, 0xf8e031e4, 0xf8e150ea, - 0xf8e5438a, 0xf8e772f4, 0xf8f56166, 0xf86883f1, - 0xf8660051, 0xf86c13be, 0xf86322db, 0xf87d31ae, - 0xf87c5311, 0xf86541c2, 0xf86a7170, 0xf87b6197, - 0xb8248236, 0xb8240261, 0xb83011b0, 0xb82e204c, - 0xb83132a3, 0xb83750c5, 0xb82741b3, 0xb83c7211, - 0xb82663a2, 0xb8a380c4, 0xb8b001b4, 0xb8ac1114, - 0xb8b92274, 0xb8a0330b, 0xb8a653f4, 0xb8ae40d0, - 0xb8a071e7, 0xb8b3613a, 0xb8ea82b7, 0xb8f6005c, - 0xb8e3126f, 0xb8f42087, 0xb8fd3007, 0xb8e95290, - 0xb8f74204, 0xb8ea7177, 0xb8f963e6, 0xb87082ed, - 0xb86c01c1, 0xb8691215, 0xb87a208f, 0xb8643110, - 0xb866509e, 0xb87d43b1, 0xb87a71e9, 0xb86263ab, - 0xce216ce3, 0xce0e2255, 0xce798ed2, 0xce959685, - 0xce7e8217, 0xce608694, 0xcec08264, 0xce748898, - 0x25e0da44, 0x2521c8f3, 0x05801548, 0x0540cbdf, - 0x05006521, 0x2560c7a0, 0x25a1c498, 0x058026bb, - 0x05407dd8, 0x0500f3d6, 0x2560ce3d, 0x2521d4b4, - 0x05803cbc, 0x05404d6c, 0x05001b89, 0x25a0c532, - 0x2521cc40, 0x05800c08, 0x054074c4, 0x050034a0, - 0x2520c9e3, 0x25e1ca93, 0x05803e98, 0x05425238, - 0x050024cb, 0x25a0ce7f, 0x25e1d0c3, 0x05802676, - 0x05401e63, 0x05002d49, 0x04e20080, 0x04ab04ce, - 0x659e022e, 0x65970863, 0x659c0703, 0x04d6b4f3, - 0x04400cb5, 0x049a06da, 0x04508071, 0x045b0d14, - 0x0459b22e, 0x04daba4d, 0x04590a13, 0x0493979b, - 0x04d188a8, 0x0450081c, 0x0417b6b9, 0x041eb743, - 0x04981e7a, 0x05e78dc1, 0x0564824e, 0x048816ff, - 0x040a0d1e, 0x04810ee0, 0x04dcb340, 0x65c08ed8, - 0x65cd8162, 0x65c6970c, 0x65c79e29, 0x65c29494, - 0x04ddbecd, 0x65c2ba5f, 0x65c0a9af, 0x6581a434, - 0x658da0ee, 0x65c1908c, 0x65be806f, 0x65ff0694, - 0x65ee2d2d, 0x65a3af81, 0x65a9cb3a, 0x65e1e9da, - 0x65f447ba, 0x65e17da6, 0x0401482b, 0x040279fb, - 0x0439323e, 0x04a33302, 0x046331bd, 0x04fc320e, - 0x05bb6964, 0x05e16e02, 0x65c897e7, 0x4596b150, - 0x4516b4fd, 0x0438396c, 0x041a280b, 0x04183697, - 0x04192de3, 0x04083b7e, 0x04ca3955, 0x65873883, - 0x658622a6, 0x65d83bd9, 0x0441303f, 0x0e2e11ac, - 0x4e2013fe, 0x0e6f11cd, 0x4e6a1128, 0x0ebb1359, - 0x4ebf13dd, 0x2e231041, 0x6e21101f, 0x2e791317, - 0x6e61101f, 0x2eb612b4, 0x6ea21020, + 0x4ead958b, 0x0e20cffe, 0x4e3dcf9b, 0x4e6bcd49, + 0x2e7b9759, 0x6e649462, 0x2eae95ac, 0x6eb39651, + 0x0ea0cffe, 0x4ea3cc41, 0x4eeecdac, 0x2e3effbc, + 0x6e22fc20, 0x6e73fe51, 0x0e2e65ac, 0x4e336651, + 0x0e7766d5, 0x4e6e65ac, 0x0ebd679b, 0x4ebf67dd, + 0x0e20a7fe, 0x4e23a441, 0x0e7ba759, 0x4e7da79b, + 0x0ea6a4a4, 0x4ebfa7dd, 0x0e25f483, 0x4e28f4e6, + 0x4e7ff7dd, 0x0e3b6f59, 0x4e336e51, 0x0e6a6d28, + 0x4e696d07, 0x0eae6dac, 0x4ea26c20, 0x0e35ae93, + 0x4e23ac41, 0x0e79af17, 0x4e64ac62, 0x0ea2ac20, + 0x4eaaad28, 0x0eb9f717, 0x4ebbf759, 0x4ef1f60f, + 0x2ebfefdd, 0x6ea5ec83, 0x6eeced6a, 0x0e3836f6, + 0x4e2c356a, 0x0e6634a4, 0x4e733651, 0x0ea33441, + 0x4ead358b, 0x4ee93507, 0x0e2c3d6a, 0x4e313e0f, + 0x0e723e30, 0x4e643c62, 0x0eab3d49, 0x4ead3d8b, + 0x4eee3dac, 0x2e308dee, 0x6e2f8dcd, 0x2e648c62, + 0x6e688ce6, 0x2eb58e93, 0x6ebb8f59, 0x6ef18e0f, + 0x2e2634a4, 0x6e243462, 0x2e6634a4, 0x6e6d358b, + 0x2eb33651, 0x6eb636b4, 0x6ef23630, 0x2e333e51, + 0x6e2c3d6a, 0x2e763eb4, 0x6e783ef6, 0x2eae3dac, + 0x6ebb3f59, 0x6ef93f17, 0x0e3ee7bc, 0x4e30e5ee, + 0x4e6ce56a, 0x2ebae738, 0x6ea3e441, 0x6eede58b, + 0x2e20e7fe, 0x6e2ce56a, 0x6e71e60f, 0x65922c43, + 0x65d02219, 0x65d02560, 0x65d13dc4, 0x65913690, + 0x65d33b6b, 0x2500948c, 0x254c08bf, 0x25831f87, + 0x254f30af, 0x259c3359, 0x25019d35, 0x24eac76d, + 0x2431993a, 0x242f7ed8, 0x24a2f62b, 0xba5fd3e3, + 0x3a5f03e5, 0xfa411be4, 0x7a42cbe2, 0x93df03ff, + 0xc820ffff, 0x8822fc7f, 0xc8247cbf, 0x88267fff, + 0x4e010fe0, 0x5e040420, 0x4e081fe1, 0x4e0c1fe1, + 0x4e0a1fe1, 0x4e071fe1, 0x4e042c20, 0x4e062c20, + 0x4e052c20, 0x4e083c20, 0x0e0c3c20, 0x0e0a3c20, + 0x0e073c20, 0x9eae0020, 0x0f03f409, 0x6f03f40e, + 0x4cc0ac3f, 0x0ea1b820, 0x4e21c862, 0x4e61b8a4, + 0x05a08020, 0x05104fe0, 0x05505001, 0x05906fe2, + 0x05d03005, 0x05101fea, 0x05901feb, 0x04b0e3e0, + 0x0470e7e1, 0x042f9c20, 0x043f9c35, 0x047f9c20, + 0x04ff9c20, 0x04299420, 0x04319160, 0x0461943e, + 0x04a19020, 0x04038100, 0x040381a0, 0x040387e1, + 0x04438be2, 0x04c38fe3, 0x040181e0, 0x04018100, + 0x04018621, 0x04418b22, 0x04418822, 0x04818c23, + 0x040081e0, 0x04008120, 0x04008761, 0x04008621, + 0x04408822, 0x04808c23, 0x042053ff, 0x047f5401, + 0x25208028, 0x2538cfe0, 0x2578d001, 0x25b8efe2, + 0x25f8f007, 0x2538dfea, 0x25b8dfeb, 0xa400a3e0, + 0xa420a7e0, 0xa4484be0, 0xa467afe0, 0xa4a8a7ea, + 0xa547a814, 0xa4084ffe, 0xa55c53e0, 0xa5e1540b, + 0xe400fbf6, 0xe408ffff, 0xe420e7e0, 0xe4484be0, + 0xe460efe0, 0xe547e400, 0xe4014be0, 0xe4a84fe0, + 0xe5f15000, 0x858043e0, 0x85a043ff, 0xe59f5d08, + 0x0420e3e9, 0x0460e3ea, 0x04a0e3eb, 0x04e0e3ec, + 0x25104042, 0x25104871, 0x25904861, 0x25904c92, + 0x05344020, 0x05744041, 0x05b44062, 0x05f44083, + 0x252c8840, 0x253c1420, 0x25681572, 0x25a21ce3, + 0x25ea1e34, 0x253c0421, 0x25680572, 0x25a20ce3, + 0x25ea0e34, 0x0522c020, 0x05e6c0a4, 0x2401a001, + 0x2443a051, 0x24858881, 0x24c78cd1, 0x24850891, + 0x24c70cc1, 0x250f9001, 0x25508051, 0x25802491, + 0x25df28c1, 0x25850c81, 0x251e10d1, 0x65816001, + 0x65c36051, 0x65854891, 0x65c74cc1, 0x05733820, + 0x05b238a4, 0x05f138e6, 0x0570396a, 0x65d0a001, + 0x65d6a443, 0x65d4a826, 0x6594ac26, 0x6554ac26, + 0x6556ac26, 0x6552ac26, 0x65cbac85, 0x65caac01, + 0x6589ac85, 0x6588ac01, 0x65c9ac85, 0x65c8ac01, + 0x65dea833, 0x659ca509, 0x65d8a801, 0x65dcac01, + 0x655cb241, 0x0520a1e0, 0x0521a601, 0x052281e0, + 0x05238601, 0x04a14026, 0x042244a6, 0x046344a6, + 0x04a444a6, 0x04e544a7, 0x0568aca7, 0x05b23230, + 0x853040af, 0xc5b040af, 0xe57080af, 0xe5b080af, + 0x25034440, 0x254054c4, 0x25034640, 0x25415a05, + 0x25834440, 0x25c54489, 0x250b5d3a, 0x2550dc20, + 0x2518e3e1, 0x2518e021, 0x2518e0a1, 0x2518e121, + 0x2518e1a1, 0x2558e3e2, 0x2558e042, 0x2558e0c2, + 0x2558e142, 0x2598e3e3, 0x2598e063, 0x2598e0e3, + 0x2598e163, 0x25d8e3e4, 0x25d8e084, 0x25d8e104, + 0x25d8e184, 0x2518e407, 0x05214800, 0x05614800, + 0x05a14800, 0x05e14800, 0x05214c00, 0x05614c00, + 0x05a14c00, 0x05e14c00, 0x05304001, 0x05314001, + 0x05a18610, 0x05e18610, 0x05271e11, 0x6545e891, + 0x6585e891, 0x65c5e891, 0x6545c891, 0x6585c891, + 0x65c5c891, 0x45b0c210, 0x45f1c231, 0x1e601000, + 0x1e603000, 0x1e621000, 0x1e623000, 0x1e641000, + 0x1e643000, 0x1e661000, 0x1e663000, 0x1e681000, + 0x1e683000, 0x1e6a1000, 0x1e6a3000, 0x1e6c1000, + 0x1e6c3000, 0x1e6e1000, 0x1e6e3000, 0x1e701000, + 0x1e703000, 0x1e721000, 0x1e723000, 0x1e741000, + 0x1e743000, 0x1e761000, 0x1e763000, 0x1e781000, + 0x1e783000, 0x1e7a1000, 0x1e7a3000, 0x1e7c1000, + 0x1e7c3000, 0x1e7e1000, 0x1e7e3000, 0xf82f8186, + 0xf83001ab, 0xf83713c1, 0xf8332225, 0xf82232d0, + 0xf82d52aa, 0xf83d419b, 0xf83b7023, 0xf83f6278, + 0xf8b18389, 0xf8bb00ef, 0xf8b513f7, 0xf8b923e2, + 0xf8bb3150, 0xf8b75073, 0xf8b04320, 0xf8ba7057, + 0xf8b0608c, 0xf8fc83be, 0xf8f000db, 0xf8e911fd, + 0xf8e720e4, 0xf8ef32e9, 0xf8e85382, 0xf8f540bf, + 0xf8fb7220, 0xf8ef6344, 0xf86882dc, 0xf87b033b, + 0xf8771080, 0xf8662010, 0xf864302f, 0xf86a50a7, + 0xf86a40fc, 0xf87472b7, 0xf866610b, 0xb83180df, + 0xb8310182, 0xb83e107d, 0xb83b23b6, 0xb82e338d, + 0xb83150b8, 0xb822414e, 0xb830736b, 0xb837608c, + 0xb8b68091, 0xb8a10213, 0xb8b011cd, 0xb8ac2222, + 0xb8a332f5, 0xb8a550e6, 0xb8b3438d, 0xb8b170d0, + 0xb8a2607d, 0xb8e481e6, 0xb8f4018d, 0xb8f41328, + 0xb8f42013, 0xb8eb30d8, 0xb8f451df, 0xb8f04006, + 0xb8e7726f, 0xb8fa6149, 0xb87782d5, 0xb87c0062, + 0xb86f1293, 0xb86723a4, 0xb8673120, 0xb87052f4, + 0xb8644150, 0xb877732b, 0xb866621f, 0xce2b06cd, + 0xce14410d, 0xce648df9, 0xce883624, 0xce7c809d, + 0xce7a87b0, 0xcec081c9, 0xce7c8962, 0x2520c143, + 0x25a1d2da, 0x058015ce, 0x05400ed8, 0x0500bb31, + 0x25a0c074, 0x25a1d884, 0x05804944, 0x0540b1d9, + 0x05001548, 0x25a0c49e, 0x2521cabe, 0x058054b3, + 0x0543ab47, 0x050026bb, 0x2560d097, 0x25a1d6fe, + 0x058394b4, 0x0540266d, 0x05003cbc, 0x25a0c1ab, + 0x2561d3f8, 0x05800acd, 0x05403684, 0x05000c07, + 0x2560de64, 0x2521cac5, 0x0583c8b5, 0x05405089, + 0x05003e98, 0x04ad0397, 0x04ac074a, 0x658e023e, + 0x65d50a1d, 0x65820667, 0x0496b13a, 0x04001411, + 0x041a19c2, 0x049095cb, 0x041b0c7d, 0x04d9a876, + 0x049aa27b, 0x04591aa7, 0x04138b25, 0x04119235, + 0x04500a63, 0x0497adc7, 0x04dea9b1, 0x04581e31, + 0x05a78f4f, 0x056494fb, 0x04481f65, 0x048a0f00, + 0x04810074, 0x04dca739, 0x65809031, 0x658d9dae, + 0x65c683d1, 0x658797b6, 0x65828008, 0x04ddb417, + 0x6582baf9, 0x6580b435, 0x65c1b56a, 0x65cdb917, + 0x65c19671, 0x65fe95a4, 0x65f11f3e, 0x65fc298e, + 0x65ada1a5, 0x65b3c967, 0x65e3ec59, 0x65f454a0, + 0x65a86dbc, 0x041b41dd, 0x04587903, 0x042a3321, + 0x04b93281, 0x0470327c, 0x04e131bb, 0x0521692b, + 0x057a6f61, 0x65c887a2, 0x45c2b058, 0x455cb723, + 0x043639a3, 0x045a309b, 0x0498305a, 0x04993ce1, + 0x04483e1e, 0x040a3395, 0x65c72595, 0x6586294b, + 0x65d826c0, 0x04412474, }; // END Generated code -- do not edit From e19c7d80f722395583fbdb4cc10dc9051c8602f2 Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Mon, 30 Sep 2024 11:24:48 +0000 Subject: [PATCH 11/15] 8340874: Open source some of the AWT Geometry/Button tests Reviewed-by: prr --- .../BadActionEventTest.java | 93 +++++++++++++ .../jdk/java/awt/geom/Arc2D/Arc2DHitTest.java | 100 ++++++++++++++ test/jdk/java/awt/geom/Arc2D/BoundsBug.java | 123 ++++++++++++++++++ test/jdk/java/awt/geom/Area/Translate.java | 122 +++++++++++++++++ 4 files changed, 438 insertions(+) create mode 100644 test/jdk/java/awt/Button/BadActionEventTest/BadActionEventTest.java create mode 100644 test/jdk/java/awt/geom/Arc2D/Arc2DHitTest.java create mode 100644 test/jdk/java/awt/geom/Arc2D/BoundsBug.java create mode 100644 test/jdk/java/awt/geom/Area/Translate.java diff --git a/test/jdk/java/awt/Button/BadActionEventTest/BadActionEventTest.java b/test/jdk/java/awt/Button/BadActionEventTest/BadActionEventTest.java new file mode 100644 index 0000000000000..53aac7ab78751 --- /dev/null +++ b/test/jdk/java/awt/Button/BadActionEventTest/BadActionEventTest.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4530087 + * @summary Test if double-clicking causes ActionEvent on underlying button + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual BadActionEventTest + */ + +import java.awt.Button; +import java.awt.Color; +import java.awt.FileDialog; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public class BadActionEventTest implements ActionListener { + private static Button showBtn; + private static Button listBtn; + + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + 1) Click on 'Show File Dialog' to bring up the FileDialog window. + (If necessary, change to a directory with files (not just directories) in it.) + 2) Move the FileDialog so that one of the file names (again, a file, NOT a directory) in the list is + directly over the 'ActionListener' button. + 3) Double-click on the file name over the button. The FileDialog will disappear. + 4) If the 'ActionListener' button receives an ActionEvent, the test fails and a + message to that effect will be printed. + Otherwise, the test passes. + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(45) + .testUI(BadActionEventTest::createUI) + .logArea(2) + .build() + .awaitAndCheck(); + } + + private static Frame createUI() { + Frame frame = new Frame("BadActionEventTest"); + frame.setLayout(new GridLayout(1, 2)); + frame.setSize(400, 200); + showBtn = new Button("Show File Dialog"); + listBtn = new Button("ActionListener"); + showBtn.setSize(200, 200); + listBtn.setSize(200, 200); + showBtn.addActionListener(new BadActionEventTest()); + listBtn.addActionListener(new BadActionEventTest()); + frame.add(showBtn); + frame.add(listBtn); + return frame; + } + + @Override + public void actionPerformed(ActionEvent e) { + if (e.getSource() == showBtn) { + FileDialog fd = new FileDialog(new Frame()); + fd.setVisible(true); + } else if (e.getSource() == listBtn) { + listBtn.setBackground(Color.red); + listBtn.setLabel("TEST FAILS!"); + PassFailJFrame.log("*TEST FAILS!* ActionListener got ActionEvent! *TEST FAILS!*"); + } + } +} diff --git a/test/jdk/java/awt/geom/Arc2D/Arc2DHitTest.java b/test/jdk/java/awt/geom/Arc2D/Arc2DHitTest.java new file mode 100644 index 0000000000000..de6b39d5c6f7f --- /dev/null +++ b/test/jdk/java/awt/geom/Arc2D/Arc2DHitTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4178123 + * @summary Verifies that the Arc2D.contains(point) methods work correctly. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual Arc2DHitTest + */ + +import java.awt.Color; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.awt.geom.Arc2D; + +public class Arc2DHitTest { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + This test displays an arc figure and lets the user click on it. + The arc will initially be drawn in red and only when the user clicks + within the arc in the window it will be redrawn into green otherwise + it should stay red. + + For convenience, the point being tested is drawn in black. Note + that rounding in the arc rendering routines may cause points near + the boundary of the arc to render incorrectly. Allow for a pixel + or two of leeway near the boundary. + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(initialize()) + .build() + .awaitAndCheck(); + } + private static Frame initialize() { + Frame f = new Frame("Arc2DHitTest"); + ArcHitPanel panel = new ArcHitPanel(); + f.add(panel); + f.setSize(300, 250); + return f; + } +} + +class ArcHitPanel extends Panel { + private Arc2D arc; + private Point hit; + public ArcHitPanel() { + arc = new Arc2D.Float(10, 10, 100, 100, 0, 120, Arc2D.PIE); + this.addMouseListener(new MouseAdapter() { + public void mouseClicked(MouseEvent e) { + hit = e.getPoint(); + repaint(); + } + }); + } + + @Override + public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D) g; + g2.setColor(Color.white); + g2.fill(g2.getClipBounds()); + g2.setColor((hit != null && arc.contains(hit)) + ? Color.green : Color.red); + g2.fill(arc); + if (hit != null) { + g2.setColor(Color.black); + g2.fillRect(hit.x, hit.y, 1, 1); + } + } +} diff --git a/test/jdk/java/awt/geom/Arc2D/BoundsBug.java b/test/jdk/java/awt/geom/Arc2D/BoundsBug.java new file mode 100644 index 0000000000000..a17f45f9dad37 --- /dev/null +++ b/test/jdk/java/awt/geom/Arc2D/BoundsBug.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4197746 + * @summary Verifies that the getBounds2D method of Arc2D returns the + * correct result. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual BoundsBug + */ + +import java.awt.Color; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.RenderingHints; +import java.awt.Shape; +import java.awt.geom.Arc2D; +import java.awt.geom.Ellipse2D; +import java.awt.geom.GeneralPath; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; + +public class BoundsBug { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + This test displays three figures and draws the outline of their + bounding boxes. The bounding boxes should correctly encompass + the 3 figures. + + This test also paints two highlight rectangles at the ends of the + angular extents of the arc. The two highlights should correctly + appear at the outer circumference of the arc where the radii lines + from its center intersect that circumference. + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(40) + .testUI(initialize()) + .build() + .awaitAndCheck(); + } + private static Frame initialize() { + Frame f = new Frame("BoundsBug"); + ArcPanel panel = new ArcPanel(); + f.add(panel); + f.setSize(300, 250); + return f; + } +} + +class ArcPanel extends Panel { + protected void drawPoint(Graphics2D g2, Point2D p) { + g2.setColor(Color.green); + g2.fill(new Rectangle2D.Double(p.getX() - 5, p.getY() - 5, 10, 10)); + } + + protected void drawShapeAndBounds(Graphics2D g2, Shape s) { + g2.setColor(Color.orange); + g2.fill(s); + g2.setColor(Color.black); + g2.draw(s); + + Rectangle2D r = s.getBounds2D(); + g2.setColor(Color.gray); + g2.draw(r); + } + + @Override + public void paint(Graphics g) { + Graphics2D g2 = (Graphics2D)g; + g2.setColor(Color.white); + g2.fill(g.getClipBounds()); + g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + // Create some interesting shapes. + Ellipse2D ellipse = new Ellipse2D.Float(20, 40, 60, 80); + Arc2D arc = new Arc2D.Float(60, 40, 100, 120, + -30, -40, Arc2D.PIE); + GeneralPath path = new GeneralPath(GeneralPath.WIND_EVEN_ODD); + path.moveTo(0, 0); + path.lineTo(75, -25); + path.lineTo(25, 75); + path.lineTo(0, 25); + path.lineTo(100, 50); + path.lineTo(50, 0); + path.lineTo(25, 50); + path.closePath(); + // Now draw them and their bounds rectangles. + drawShapeAndBounds(g2, ellipse); + drawShapeAndBounds(g2, arc); + drawPoint(g2, arc.getStartPoint()); + drawPoint(g2, arc.getEndPoint()); + g2.translate(180, 65); + drawShapeAndBounds(g2, path); + } +} diff --git a/test/jdk/java/awt/geom/Area/Translate.java b/test/jdk/java/awt/geom/Area/Translate.java new file mode 100644 index 0000000000000..7519f1753bcf3 --- /dev/null +++ b/test/jdk/java/awt/geom/Area/Translate.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 4183373 + * @summary Verifies that the translated Area objects display correctly + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual Translate + */ + +import java.awt.BorderLayout; +import java.awt.CardLayout; +import java.awt.Color; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Image; +import java.awt.Panel; +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.awt.geom.Area; +import java.awt.geom.Rectangle2D; + +public class Translate { + public static void main(String[] args) throws Exception { + String INSTRUCTIONS = """ + This test displays two sets of rectangular figures. The two sets + should be displayed one on top of the other and should be lined + up vertically with each other. If the two sets of figures are + not directly above and below each other then the test fails + """; + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(35) + .testUI(initialize()) + .build() + .awaitAndCheck(); + } + private static Frame initialize() { + Frame f = new Frame("Translate"); + TranslatePanel panel = new TranslatePanel(); + f.add(panel); + f.setSize(300, 250); + return f; + } +} + +class TranslatePanel extends Panel { + private static Image bufferedImage; + private static Area a1, a2, a3; + + public TranslatePanel() { + a1 = new Area(new Rectangle2D.Double(20.0, 20.0, 60.0, 60.0)); + + a2 = new Area((Area) a1.clone()); + a2.subtract(new Area(new Rectangle2D.Double(30.0, 30.0, 40.0, 40.0))); + + a3 = new Area((Area) a2.clone()); + a3.add(new Area(new Rectangle2D.Double(40.0, 40.0, 20.0, 20.0))); + + AffineTransform at2 = new AffineTransform(); + at2.translate(100.0, 0.0); + a2.transform(at2); + + AffineTransform at3 = new AffineTransform(); + at3.translate(200.0, 0.0); + a3.transform(at3); + } + private void paintRects(Graphics2D g2) { + Rectangle clip = g2.getClipBounds(); + g2.setColor(Color.white); + g2.fillRect(clip.x, clip.y, clip.width, clip.height); + g2.setPaint(Color.red); + g2.fill(a1); + g2.setPaint(Color.yellow); + g2.fill(a2); + g2.setPaint(Color.blue); + g2.fill(a3); + } + + @Override + public void paint(Graphics g) { + if (bufferedImage == null) { + bufferedImage = createImage(300, 100); + Graphics big = bufferedImage.getGraphics(); + // Notice that if you remove the translate() call, it works fine. + big.translate(-1, -1); + big.setClip(1, 1, 300, 100); + paintRects((Graphics2D)big); + big.translate(1, 1); + } + paintRects((Graphics2D)g); + g.drawImage(bufferedImage, 1, 100, this); + g.setColor(Color.black); + g.drawString("From offscreen image (with translate):", 10, 95); + g.drawString(" (should line up with rectangles above)", 10, 110); + } +} From 180affc5718c9bf2f009d6a7aa129cc36335384a Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Mon, 30 Sep 2024 12:28:35 +0000 Subject: [PATCH 12/15] 8320318: ObjectMonitor Responsible thread Reviewed-by: aboldtch, coleenp, pchilanomate, eosterlund --- .../cpu/aarch64/c2_MacroAssembler_aarch64.cpp | 72 +++- src/hotspot/cpu/ppc/macroAssembler_ppc.cpp | 61 +++- .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 62 +++- src/hotspot/cpu/s390/macroAssembler_s390.cpp | 74 +++- src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp | 56 +-- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 133 +++---- src/hotspot/share/opto/c2_CodeStubs.hpp | 2 - src/hotspot/share/runtime/javaThread.cpp | 1 + src/hotspot/share/runtime/javaThread.hpp | 8 + src/hotspot/share/runtime/objectMonitor.cpp | 335 +++++++----------- src/hotspot/share/runtime/objectMonitor.hpp | 9 +- .../share/runtime/objectMonitor.inline.hpp | 19 +- src/hotspot/share/runtime/sharedRuntime.cpp | 20 ++ .../org/openjdk/bench/vm/lang/LockUnlock.java | 7 +- 14 files changed, 438 insertions(+), 421 deletions(-) diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index b4c12ecd4a849..62831ee72ba05 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -150,10 +150,12 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Registe Register oop = objectReg; Register box = boxReg; Register disp_hdr = tmpReg; + Register owner_addr = tmpReg; Register tmp = tmp2Reg; Label cont; Label object_has_monitor; Label count, no_count; + Label unlocked; assert(LockingMode != LM_LIGHTWEIGHT, "lightweight locking should use fast_unlock_lightweight"); assert_different_registers(oop, box, tmp, disp_hdr); @@ -204,14 +206,40 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Registe b(cont); bind(notRecursive); + + // Compute owner address. + lea(owner_addr, Address(tmp, ObjectMonitor::owner_offset())); + + // Set owner to null. + // Release to satisfy the JMM + stlr(zr, owner_addr); + // We need a full fence after clearing owner to avoid stranding. + // StoreLoad achieves this. + membar(StoreLoad); + + // Check if the entry lists are empty. ldr(rscratch1, Address(tmp, ObjectMonitor::EntryList_offset())); - ldr(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset())); - orr(rscratch1, rscratch1, disp_hdr); // Will be 0 if both are 0. - cmp(rscratch1, zr); // Sets flags for result - cbnz(rscratch1, cont); - // need a release store here - lea(tmp, Address(tmp, ObjectMonitor::owner_offset())); - stlr(zr, tmp); // set unowned + ldr(tmpReg, Address(tmp, ObjectMonitor::cxq_offset())); + orr(rscratch1, rscratch1, tmpReg); + cmp(rscratch1, zr); + br(Assembler::EQ, cont); // If so we are done. + + // Check if there is a successor. + ldr(rscratch1, Address(tmp, ObjectMonitor::succ_offset())); + cmp(rscratch1, zr); + br(Assembler::NE, unlocked); // If so we are done. + + // Save the monitor pointer in the current thread, so we can try to + // reacquire the lock in SharedRuntime::monitor_exit_helper(). + str(tmp, Address(rthread, JavaThread::unlocked_inflated_monitor_offset())); + + cmp(zr, rthread); // Set Flag to NE => slow path + b(cont); + + bind(unlocked); + cmp(zr, zr); // Set Flag to EQ => fast path + + // Intentional fall-through bind(cont); // flag == EQ indicates success @@ -498,33 +526,41 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register box, Regi bind(not_recursive); - Label release; const Register t2_owner_addr = t2; // Compute owner address. lea(t2_owner_addr, Address(t1_monitor, ObjectMonitor::owner_offset())); + // Set owner to null. + // Release to satisfy the JMM + stlr(zr, t2_owner_addr); + // We need a full fence after clearing owner to avoid stranding. + // StoreLoad achieves this. + membar(StoreLoad); + // Check if the entry lists are empty. ldr(rscratch1, Address(t1_monitor, ObjectMonitor::EntryList_offset())); ldr(t3_t, Address(t1_monitor, ObjectMonitor::cxq_offset())); orr(rscratch1, rscratch1, t3_t); cmp(rscratch1, zr); - br(Assembler::EQ, release); + br(Assembler::EQ, unlocked); // If so we are done. - // The owner may be anonymous and we removed the last obj entry in - // the lock-stack. This loses the information about the owner. - // Write the thread to the owner field so the runtime knows the owner. - str(rthread, Address(t2_owner_addr)); - b(slow_path); + // Check if there is a successor. + ldr(rscratch1, Address(t1_monitor, ObjectMonitor::succ_offset())); + cmp(rscratch1, zr); + br(Assembler::NE, unlocked); // If so we are done. - bind(release); - // Set owner to null. - // Release to satisfy the JMM - stlr(zr, t2_owner_addr); + // Save the monitor pointer in the current thread, so we can try to + // reacquire the lock in SharedRuntime::monitor_exit_helper(). + str(t1_monitor, Address(rthread, JavaThread::unlocked_inflated_monitor_offset())); + + cmp(zr, rthread); // Set Flag to NE => slow path + b(slow_path); } bind(unlocked); decrement(Address(rthread, JavaThread::held_monitor_count_offset())); + cmp(zr, zr); // Set Flags to EQ => fast path #ifdef ASSERT // Check that unlocked label is reached with Flags == EQ. diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp index a8635af9582d1..8d8e39b8bbc00 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.cpp @@ -2715,13 +2715,34 @@ void MacroAssembler::compiler_fast_unlock_object(ConditionRegister flag, Registe b(success); bind(notRecursive); + + // Set owner to null. + // Release to satisfy the JMM + release(); + li(temp, 0); + std(temp, in_bytes(ObjectMonitor::owner_offset()), current_header); + // We need a full fence after clearing owner to avoid stranding. + // StoreLoad achieves this. + membar(StoreLoad); + + // Check if the entry lists are empty. ld(temp, in_bytes(ObjectMonitor::EntryList_offset()), current_header); ld(displaced_header, in_bytes(ObjectMonitor::cxq_offset()), current_header); orr(temp, temp, displaced_header); // Will be 0 if both are 0. cmpdi(flag, temp, 0); - bne(flag, failure); - release(); - std(temp, in_bytes(ObjectMonitor::owner_offset()), current_header); + beq(flag, success); // If so we are done. + + // Check if there is a successor. + ld(temp, in_bytes(ObjectMonitor::succ_offset()), current_header); + cmpdi(flag, temp, 0); + bne(flag, success); // If so we are done. + + // Save the monitor pointer in the current thread, so we can try + // to reacquire the lock in SharedRuntime::monitor_exit_helper(). + std(current_header, in_bytes(JavaThread::unlocked_inflated_monitor_offset()), R16_thread); + + crxor(flag, Assembler::equal, flag, Assembler::equal); // Set flag = NE => slow path + b(failure); // flag == EQ indicates success, decrement held monitor count // flag == NE indicates failure @@ -3028,27 +3049,39 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(ConditionRegister f bind(not_recursive); - Label release_; + Label set_eq_unlocked; const Register t2 = tmp2; + // Set owner to null. + // Release to satisfy the JMM + release(); + li(t, 0); + std(t, in_bytes(ObjectMonitor::owner_offset()), monitor); + // We need a full fence after clearing owner to avoid stranding. + // StoreLoad achieves this. + membar(StoreLoad); + // Check if the entry lists are empty. ld(t, in_bytes(ObjectMonitor::EntryList_offset()), monitor); ld(t2, in_bytes(ObjectMonitor::cxq_offset()), monitor); orr(t, t, t2); cmpdi(CCR0, t, 0); - beq(CCR0, release_); + beq(CCR0, unlocked); // If so we are done. - // The owner may be anonymous and we removed the last obj entry in - // the lock-stack. This loses the information about the owner. - // Write the thread to the owner field so the runtime knows the owner. - std(R16_thread, in_bytes(ObjectMonitor::owner_offset()), monitor); + // Check if there is a successor. + ld(t, in_bytes(ObjectMonitor::succ_offset()), monitor); + cmpdi(CCR0, t, 0); + bne(CCR0, set_eq_unlocked); // If so we are done. + + // Save the monitor pointer in the current thread, so we can try + // to reacquire the lock in SharedRuntime::monitor_exit_helper(). + std(monitor, in_bytes(JavaThread::unlocked_inflated_monitor_offset()), R16_thread); + + crxor(CCR0, Assembler::equal, CCR0, Assembler::equal); // Set flag = NE => slow path b(slow_path); - bind(release_); - // Set owner to null. - release(); - // t contains 0 - std(t, in_bytes(ObjectMonitor::owner_offset()), monitor); + bind(set_eq_unlocked); + crorc(CCR0, Assembler::equal, CCR0, Assembler::equal); // Set flag = EQ => fast path } bind(unlocked); diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index e2c9b9dd609e0..75f87e35adf41 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -165,6 +165,7 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, Register oop = objectReg; Register box = boxReg; Register disp_hdr = tmp1Reg; + Register owner_addr = tmp1Reg; Register tmp = tmp2Reg; Label object_has_monitor; // Finish fast lock successfully. MUST branch to with flag == 0 @@ -222,15 +223,33 @@ void C2_MacroAssembler::fast_unlock(Register objectReg, Register boxReg, j(unlocked); bind(notRecursive); - ld(t0, Address(tmp, ObjectMonitor::EntryList_offset())); - ld(disp_hdr, Address(tmp, ObjectMonitor::cxq_offset())); - orr(t0, t0, disp_hdr); // Will be 0 if both are 0. - bnez(t0, slow_path); + // Compute owner address. + la(owner_addr, Address(tmp, ObjectMonitor::owner_offset())); - // need a release store here - la(tmp, Address(tmp, ObjectMonitor::owner_offset())); + // Set owner to null. + // Release to satisfy the JMM membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); - sd(zr, Address(tmp)); // set unowned + sd(zr, Address(owner_addr)); + // We need a full fence after clearing owner to avoid stranding. + // StoreLoad achieves this. + membar(StoreLoad); + + // Check if the entry lists are empty. + ld(t0, Address(tmp, ObjectMonitor::EntryList_offset())); + ld(tmp1Reg, Address(tmp, ObjectMonitor::cxq_offset())); + orr(t0, t0, tmp1Reg); + beqz(t0, unlocked); // If so we are done. + + // Check if there is a successor. + ld(t0, Address(tmp, ObjectMonitor::succ_offset())); + bnez(t0, unlocked); // If so we are done. + + // Save the monitor pointer in the current thread, so we can try to + // reacquire the lock in SharedRuntime::monitor_exit_helper(). + sd(tmp, Address(xthread, JavaThread::unlocked_inflated_monitor_offset())); + + mv(flag, 1); + j(slow_path); bind(unlocked); mv(flag, zr); @@ -534,28 +553,35 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register box, bind(not_recursive); - Label release; const Register tmp2_owner_addr = tmp2; // Compute owner address. la(tmp2_owner_addr, Address(tmp1_monitor, ObjectMonitor::owner_offset())); + // Set owner to null. + // Release to satisfy the JMM + membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + sd(zr, Address(tmp2_owner_addr)); + // We need a full fence after clearing owner to avoid stranding. + // StoreLoad achieves this. + membar(StoreLoad); + // Check if the entry lists are empty. ld(t0, Address(tmp1_monitor, ObjectMonitor::EntryList_offset())); ld(tmp3_t, Address(tmp1_monitor, ObjectMonitor::cxq_offset())); orr(t0, t0, tmp3_t); - beqz(t0, release); + beqz(t0, unlocked); // If so we are done. - // The owner may be anonymous and we removed the last obj entry in - // the lock-stack. This loses the information about the owner. - // Write the thread to the owner field so the runtime knows the owner. - sd(xthread, Address(tmp2_owner_addr)); - j(slow_path); + // Check if there is a successor. + ld(tmp3_t, Address(tmp1_monitor, ObjectMonitor::succ_offset())); + bnez(tmp3_t, unlocked); // If so we are done. - bind(release); - // Set owner to null. - membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); - sd(zr, Address(tmp2_owner_addr)); + // Save the monitor pointer in the current thread, so we can try + // to reacquire the lock in SharedRuntime::monitor_exit_helper(). + sd(tmp1_monitor, Address(xthread, JavaThread::unlocked_inflated_monitor_offset())); + + mv(flag, 1); + j(slow_path); } bind(unlocked); diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 6c26e17d5ce3b..af281345b1477 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -3655,12 +3655,38 @@ void MacroAssembler::compiler_fast_unlock_object(Register oop, Register box, Reg bind(not_recursive); + NearLabel check_succ, set_eq_unlocked; + + // Set owner to null. + // Release to satisfy the JMM + z_release(); + z_lghi(temp, 0); + z_stg(temp, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), currentHeader); + // We need a full fence after clearing owner to avoid stranding. + z_fence(); + + // Check if the entry lists are empty. load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList))); - z_brne(done); + z_brne(check_succ); load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq))); - z_brne(done); - z_release(); - z_stg(temp/*=0*/, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner), currentHeader); + z_bre(done); // If so we are done. + + bind(check_succ); + + // Check if there is a successor. + load_and_test_long(temp, Address(currentHeader, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ))); + z_brne(set_eq_unlocked); // If so we are done. + + // Save the monitor pointer in the current thread, so we can try to + // reacquire the lock in SharedRuntime::monitor_exit_helper(). + z_xilf(currentHeader, markWord::monitor_value); + z_stg(currentHeader, Address(Z_thread, JavaThread::unlocked_inflated_monitor_offset())); + + z_ltgr(oop, oop); // Set flag = NE + z_bru(done); + + bind(set_eq_unlocked); + z_cr(temp, temp); // Set flag = EQ bind(done); @@ -6454,6 +6480,7 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(Register obj, Regis const ByteSize monitor_tag = in_ByteSize(UseObjectMonitorTable ? 0 : checked_cast(markWord::monitor_value)); const Address recursions_address{monitor, ObjectMonitor::recursions_offset() - monitor_tag}; const Address cxq_address{monitor, ObjectMonitor::cxq_offset() - monitor_tag}; + const Address succ_address{monitor, ObjectMonitor::succ_offset() - monitor_tag}; const Address EntryList_address{monitor, ObjectMonitor::EntryList_offset() - monitor_tag}; const Address owner_address{monitor, ObjectMonitor::owner_offset() - monitor_tag}; @@ -6471,25 +6498,40 @@ void MacroAssembler::compiler_fast_unlock_lightweight_object(Register obj, Regis bind(not_recursive); - NearLabel not_ok; + NearLabel check_succ, set_eq_unlocked; + + // Set owner to null. + // Release to satisfy the JMM + z_release(); + z_lghi(tmp2, 0); + z_stg(tmp2 /*=0*/, owner_address); + // We need a full fence after clearing owner to avoid stranding. + z_fence(); + // Check if the entry lists are empty. load_and_test_long(tmp2, EntryList_address); - z_brne(not_ok); + z_brne(check_succ); load_and_test_long(tmp2, cxq_address); - z_brne(not_ok); + z_bre(unlocked); // If so we are done. - z_release(); - z_stg(tmp2 /*=0*/, owner_address); + bind(check_succ); - z_bru(unlocked); // CC = EQ here + // Check if there is a successor. + load_and_test_long(tmp2, succ_address); + z_brne(set_eq_unlocked); // If so we are done. - bind(not_ok); + // Save the monitor pointer in the current thread, so we can try to + // reacquire the lock in SharedRuntime::monitor_exit_helper(). + if (!UseObjectMonitorTable) { + z_xilf(monitor, markWord::monitor_value); + } + z_stg(monitor, Address(Z_thread, JavaThread::unlocked_inflated_monitor_offset())); + + z_ltgr(obj, obj); // Set flag = NE + z_bru(slow_path); - // The owner may be anonymous, and we removed the last obj entry in - // the lock-stack. This loses the information about the owner. - // Write the thread to the owner field so the runtime knows the owner. - z_stg(Z_thread, owner_address); - z_bru(slow_path); // CC = NE here + bind(set_eq_unlocked); + z_cr(tmp2, tmp2); // Set flag = EQ } bind(unlocked); diff --git a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp index 1990488d8a0df..44f897529e7ce 100644 --- a/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp +++ b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp @@ -80,8 +80,6 @@ int C2FastUnlockLightweightStub::max_size() const { void C2FastUnlockLightweightStub::emit(C2_MacroAssembler& masm) { assert(_t == rax, "must be"); - Label restore_held_monitor_count_and_slow_path; - { // Restore lock-stack and handle the unlock in runtime. __ bind(_push_and_slow_path); @@ -91,61 +89,9 @@ void C2FastUnlockLightweightStub::emit(C2_MacroAssembler& masm) { __ movptr(Address(_thread, _t), _obj); #endif __ addl(Address(_thread, JavaThread::lock_stack_top_offset()), oopSize); - } - - { // Restore held monitor count and slow path. - - __ bind(restore_held_monitor_count_and_slow_path); - __ bind(_slow_path); - // Restore held monitor count. - __ increment(Address(_thread, JavaThread::held_monitor_count_offset())); - // increment will always result in ZF = 0 (no overflows). + // addl will always result in ZF = 0 (no overflows). __ jmp(slow_path_continuation()); } - - { // Handle monitor medium path. - - __ bind(_check_successor); - - Label fix_zf_and_unlocked; - const Register monitor = _mark; - -#ifndef _LP64 - __ jmpb(restore_held_monitor_count_and_slow_path); -#else // _LP64 - const ByteSize monitor_tag = in_ByteSize(UseObjectMonitorTable ? 0 : checked_cast(markWord::monitor_value)); - const Address succ_address(monitor, ObjectMonitor::succ_offset() - monitor_tag); - const Address owner_address(monitor, ObjectMonitor::owner_offset() - monitor_tag); - - // successor null check. - __ cmpptr(succ_address, NULL_WORD); - __ jccb(Assembler::equal, restore_held_monitor_count_and_slow_path); - - // Release lock. - __ movptr(owner_address, NULL_WORD); - - // Fence. - // Instead of MFENCE we use a dummy locked add of 0 to the top-of-stack. - __ lock(); __ addl(Address(rsp, 0), 0); - - // Recheck successor. - __ cmpptr(succ_address, NULL_WORD); - // Observed a successor after the release -> fence we have handed off the monitor - __ jccb(Assembler::notEqual, fix_zf_and_unlocked); - - // Try to relock, if it fails the monitor has been handed over - // TODO: Caveat, this may fail due to deflation, which does - // not handle the monitor handoff. Currently only works - // due to the responsible thread. - __ xorptr(rax, rax); - __ lock(); __ cmpxchgptr(_thread, owner_address); - __ jccb (Assembler::equal, restore_held_monitor_count_and_slow_path); -#endif - - __ bind(fix_zf_and_unlocked); - __ xorl(rax, rax); - __ jmp(unlocked_continuation()); - } } #undef __ diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index c2801a791cb5a..839745f76ec6a 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -459,87 +459,43 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t // IA32's memory-model is SPO, so STs are ordered with respect to // each other and there's no need for an explicit barrier (fence). // See also http://gee.cs.oswego.edu/dl/jmm/cookbook.html. -#ifndef _LP64 - // Note that we could employ various encoding schemes to reduce - // the number of loads below (currently 4) to just 2 or 3. - // Refer to the comments in synchronizer.cpp. - // In practice the chain of fetches doesn't seem to impact performance, however. - xorptr(boxReg, boxReg); - orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); - jccb (Assembler::notZero, DONE_LABEL); - movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList))); - orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq))); - jccb (Assembler::notZero, DONE_LABEL); - movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD); - jmpb (DONE_LABEL); -#else // _LP64 - // It's inflated - Label CheckSucc, LNotRecursive, LSuccess, LGoSlowPath; + Label LSuccess, LNotRecursive; cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions)), 0); jccb(Assembler::equal, LNotRecursive); // Recursive inflated unlock - decq(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); + decrement(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(recursions))); jmpb(LSuccess); bind(LNotRecursive); - movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq))); - orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList))); - jccb (Assembler::notZero, CheckSucc); - // Without cast to int32_t this style of movptr will destroy r10 which is typically obj. + + // Set owner to null. + // Release to satisfy the JMM movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD); - jmpb (DONE_LABEL); + // We need a full fence after clearing owner to avoid stranding. + // StoreLoad achieves this. + membar(StoreLoad); - // Try to avoid passing control into the slow_path ... - bind (CheckSucc); + // Check if the entry lists are empty. + movptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(cxq))); + orptr(boxReg, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(EntryList))); + jccb(Assembler::zero, LSuccess); // If so we are done. - // The following optional optimization can be elided if necessary - // Effectively: if (succ == null) goto slow path - // The code reduces the window for a race, however, - // and thus benefits performance. + // Check if there is a successor. cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), NULL_WORD); - jccb (Assembler::zero, LGoSlowPath); - - xorptr(boxReg, boxReg); - // Without cast to int32_t this style of movptr will destroy r10 which is typically obj. - movptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner)), NULL_WORD); + jccb(Assembler::notZero, LSuccess); // If so we are done. - // Memory barrier/fence - // Dekker pivot point -- fulcrum : ST Owner; MEMBAR; LD Succ - // Instead of MFENCE we use a dummy locked add of 0 to the top-of-stack. - // This is faster on Nehalem and AMD Shanghai/Barcelona. - // See https://blogs.oracle.com/dave/entry/instruction_selection_for_volatile_fences - // We might also restructure (ST Owner=0;barrier;LD _Succ) to - // (mov box,0; xchgq box, &m->Owner; LD _succ) . - lock(); addl(Address(rsp, 0), 0); + // Save the monitor pointer in the current thread, so we can try to + // reacquire the lock in SharedRuntime::monitor_exit_helper(). + andptr(tmpReg, ~(int32_t)markWord::monitor_value); +#ifndef _LP64 + get_thread(boxReg); + movptr(Address(boxReg, JavaThread::unlocked_inflated_monitor_offset()), tmpReg); +#else // _LP64 + movptr(Address(r15_thread, JavaThread::unlocked_inflated_monitor_offset()), tmpReg); +#endif - cmpptr(Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(succ)), NULL_WORD); - jccb (Assembler::notZero, LSuccess); - - // Rare inopportune interleaving - race. - // The successor vanished in the small window above. - // The lock is contended -- (cxq|EntryList) != null -- and there's no apparent successor. - // We need to ensure progress and succession. - // Try to reacquire the lock. - // If that fails then the new owner is responsible for succession and this - // thread needs to take no further action and can exit via the fast path (success). - // If the re-acquire succeeds then pass control into the slow path. - // As implemented, this latter mode is horrible because we generated more - // coherence traffic on the lock *and* artificially extended the critical section - // length while by virtue of passing control into the slow path. - - // box is really RAX -- the following CMPXCHG depends on that binding - // cmpxchg R,[M] is equivalent to rax = CAS(M,rax,R) - lock(); - cmpxchgptr(r15_thread, Address(tmpReg, OM_OFFSET_NO_MONITOR_VALUE_TAG(owner))); - // There's no successor so we tried to regrab the lock. - // If that didn't work, then another thread grabbed the - // lock so we're done (and exit was a success). - jccb (Assembler::notEqual, LSuccess); - // Intentional fall-through into slow path - - bind (LGoSlowPath); orl (boxReg, 1); // set ICC.ZF=0 to indicate failure jmpb (DONE_LABEL); @@ -547,7 +503,6 @@ void C2_MacroAssembler::fast_unlock(Register objReg, Register boxReg, Register t testl (boxReg, 0); // set ICC.ZF=1 to indicate success jmpb (DONE_LABEL); -#endif if (LockingMode == LM_LEGACY) { bind (Stacked); movptr(tmpReg, Address (boxReg, 0)); // re-fetch @@ -744,10 +699,7 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, // Handle inflated monitor. Label inflated, inflated_check_lock_stack; // Finish fast unlock successfully. MUST jump with ZF == 1 - Label unlocked; - - // Assume success. - decrement(Address(thread, JavaThread::held_monitor_count_offset())); + Label unlocked, slow_path; const Register mark = t; const Register monitor = t; @@ -763,8 +715,6 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, } Label& push_and_slow_path = stub == nullptr ? dummy : stub->push_and_slow_path(); - Label& check_successor = stub == nullptr ? dummy : stub->check_successor(); - Label& slow_path = stub == nullptr ? dummy : stub->slow_path(); { // Lightweight Unlock @@ -839,6 +789,7 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, const ByteSize monitor_tag = in_ByteSize(UseObjectMonitorTable ? 0 : checked_cast(markWord::monitor_value)); const Address recursions_address{monitor, ObjectMonitor::recursions_offset() - monitor_tag}; const Address cxq_address{monitor, ObjectMonitor::cxq_offset() - monitor_tag}; + const Address succ_address{monitor, ObjectMonitor::succ_offset() - monitor_tag}; const Address EntryList_address{monitor, ObjectMonitor::EntryList_offset() - monitor_tag}; const Address owner_address{monitor, ObjectMonitor::owner_offset() - monitor_tag}; @@ -846,27 +797,42 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, // Check if recursive. cmpptr(recursions_address, 0); - jccb(Assembler::notEqual, recursive); + jccb(Assembler::notZero, recursive); + + // Set owner to null. + // Release to satisfy the JMM + movptr(owner_address, NULL_WORD); + // We need a full fence after clearing owner to avoid stranding. + // StoreLoad achieves this. + membar(StoreLoad); // Check if the entry lists are empty. movptr(reg_rax, cxq_address); orptr(reg_rax, EntryList_address); - jcc(Assembler::notZero, check_successor); + jccb(Assembler::zero, unlocked); // If so we are done. - // Release lock. - movptr(owner_address, NULL_WORD); - jmpb(unlocked); + // Check if there is a successor. + cmpptr(succ_address, NULL_WORD); + jccb(Assembler::notZero, unlocked); // If so we are done. + + // Save the monitor pointer in the current thread, so we can try to + // reacquire the lock in SharedRuntime::monitor_exit_helper(). + if (!UseObjectMonitorTable) { + andptr(monitor, ~(int32_t)markWord::monitor_value); + } + movptr(Address(thread, JavaThread::unlocked_inflated_monitor_offset()), monitor); + + testl(monitor, monitor); // Fast Unlock ZF = 0 + jmpb(slow_path); // Recursive unlock. bind(recursive); decrement(recursions_address); - xorl(t, t); } bind(unlocked); - if (stub != nullptr) { - bind(stub->unlocked_continuation()); - } + decrement(Address(thread, JavaThread::held_monitor_count_offset())); + xorl(t, t); // Fast Unlock ZF = 1 #ifdef ASSERT // Check that unlocked label is reached with ZF set. @@ -875,6 +841,7 @@ void C2_MacroAssembler::fast_unlock_lightweight(Register obj, Register reg_rax, stop("Fast Unlock ZF != 1"); #endif + bind(slow_path); if (stub != nullptr) { bind(stub->slow_path_continuation()); } diff --git a/src/hotspot/share/opto/c2_CodeStubs.hpp b/src/hotspot/share/opto/c2_CodeStubs.hpp index 5db7596e072dc..318bc2f45fc76 100644 --- a/src/hotspot/share/opto/c2_CodeStubs.hpp +++ b/src/hotspot/share/opto/c2_CodeStubs.hpp @@ -105,7 +105,6 @@ class C2FastUnlockLightweightStub : public C2CodeStub { Register _thread; Label _slow_path; Label _push_and_slow_path; - Label _check_successor; Label _unlocked_continuation; public: C2FastUnlockLightweightStub(Register obj, Register mark, Register t, Register thread) : C2CodeStub(), @@ -114,7 +113,6 @@ class C2FastUnlockLightweightStub : public C2CodeStub { void emit(C2_MacroAssembler& masm); Label& slow_path() { return _slow_path; } Label& push_and_slow_path() { return _push_and_slow_path; } - Label& check_successor() { return _check_successor; } Label& unlocked_continuation() { return _unlocked_continuation; } Label& slow_path_continuation() { return continuation(); } }; diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 3528fc5b1bced..14528f6d908fc 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -487,6 +487,7 @@ JavaThread::JavaThread(MemTag mem_tag) : _cont_fastpath_thread_state(1), _held_monitor_count(0), _jni_monitor_count(0), + _unlocked_inflated_monitor(nullptr), _handshake(this), diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index e36b7dfe888a8..20bb08a4acbca 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -464,6 +464,7 @@ class JavaThread: public Thread { // It's signed for error detection. intx _held_monitor_count; // used by continuations for fast lock detection intx _jni_monitor_count; + ObjectMonitor* _unlocked_inflated_monitor; private: @@ -615,6 +616,12 @@ class JavaThread: public Thread { intx jni_monitor_count() { return _jni_monitor_count; } void clear_jni_monitor_count() { _jni_monitor_count = 0; } + // Support for SharedRuntime::monitor_exit_helper() + ObjectMonitor* unlocked_inflated_monitor() const { return _unlocked_inflated_monitor; } + void clear_unlocked_inflated_monitor() { + _unlocked_inflated_monitor = nullptr; + } + inline bool is_vthread_mounted() const; inline const ContinuationEntry* vthread_continuation() const; @@ -828,6 +835,7 @@ class JavaThread: public Thread { static ByteSize cont_fastpath_offset() { return byte_offset_of(JavaThread, _cont_fastpath); } static ByteSize held_monitor_count_offset() { return byte_offset_of(JavaThread, _held_monitor_count); } static ByteSize jni_monitor_count_offset() { return byte_offset_of(JavaThread, _jni_monitor_count); } + static ByteSize unlocked_inflated_monitor_offset() { return byte_offset_of(JavaThread, _unlocked_inflated_monitor); } #if INCLUDE_JVMTI static ByteSize is_in_VTMS_transition_offset() { return byte_offset_of(JavaThread, _is_in_VTMS_transition); } diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 367d79a5283db..755d49d2c6c58 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -178,7 +178,7 @@ OopStorage* ObjectMonitor::_oop_storage = nullptr; // // Cxq points to the set of Recently Arrived Threads attempting entry. // Because we push threads onto _cxq with CAS, the RATs must take the form of -// a singly-linked LIFO. We drain _cxq into EntryList at unlock-time when +// a singly-linked LIFO. We drain _cxq into EntryList at unlock-time when // the unlocking thread notices that EntryList is null but _cxq is != null. // // The EntryList is ordered by the prevailing queue discipline and @@ -210,19 +210,6 @@ OopStorage* ObjectMonitor::_oop_storage = nullptr; // unpark the notifyee. Unparking a notifee in notify() is inefficient - // it's likely the notifyee would simply impale itself on the lock held // by the notifier. -// -// * An interesting alternative is to encode cxq as (List,LockByte) where -// the LockByte is 0 iff the monitor is owned. _owner is simply an auxiliary -// variable, like _recursions, in the scheme. The threads or Events that form -// the list would have to be aligned in 256-byte addresses. A thread would -// try to acquire the lock or enqueue itself with CAS, but exiting threads -// could use a 1-0 protocol and simply STB to set the LockByte to 0. -// Note that is is *not* word-tearing, but it does presume that full-word -// CAS operations are coherent with intermix with STB operations. That's true -// on most common processors. -// -// * See also http://blogs.sun.com/dave - // Check that object() and set_object() are called from the right context: static void check_object_context() { @@ -257,7 +244,6 @@ ObjectMonitor::ObjectMonitor(oop object) : _EntryList(nullptr), _cxq(nullptr), _succ(nullptr), - _Responsible(nullptr), _SpinDuration(ObjectMonitor::Knob_SpinLimit), _contentions(0), _WaitSet(nullptr), @@ -320,17 +306,11 @@ bool ObjectMonitor::enter_is_async_deflating() { return false; } -void ObjectMonitor::enter_for_with_contention_mark(JavaThread* locking_thread, ObjectMonitorContentionMark& contention_mark) { - // Used by ObjectSynchronizer::enter_for to enter for another thread. - // The monitor is private to or already owned by locking_thread which must be suspended. - // So this code may only contend with deflation. - assert(locking_thread == Thread::current() || locking_thread->is_obj_deopt_suspend(), "must be"); +bool ObjectMonitor::TryLockWithContentionMark(JavaThread* locking_thread, ObjectMonitorContentionMark& contention_mark) { assert(contention_mark._monitor == this, "must be"); assert(!is_being_async_deflated(), "must be"); - void* prev_owner = try_set_owner_from(nullptr, locking_thread); - bool success = false; if (prev_owner == nullptr) { @@ -343,8 +323,16 @@ void ObjectMonitor::enter_for_with_contention_mark(JavaThread* locking_thread, O // Racing with deflation. prev_owner = try_set_owner_from(DEFLATER_MARKER, locking_thread); if (prev_owner == DEFLATER_MARKER) { - // Cancelled deflation. Increment contentions as part of the deflation protocol. - add_to_contentions(1); + // We successfully cancelled the in-progress async deflation by + // changing owner from DEFLATER_MARKER to current. We now extend + // the lifetime of the contention_mark (e.g. contentions++) here + // to prevent the deflater thread from winning the last part of + // the 2-part async deflation protocol after the regular + // decrement occurs when the contention_mark goes out of + // scope. ObjectMonitor::deflate_monitor() which is called by + // the deflater thread will decrement contentions after it + // recognizes that the async deflation was cancelled. + contention_mark.extend(); success = true; } else if (prev_owner == nullptr) { // At this point we cannot race with deflation as we have both incremented @@ -360,12 +348,28 @@ void ObjectMonitor::enter_for_with_contention_mark(JavaThread* locking_thread, O set_owner_from_BasicLock(prev_owner, locking_thread); success = true; } + assert(!success || owner_raw() == locking_thread, "must be"); + + return success; +} + +void ObjectMonitor::enter_for_with_contention_mark(JavaThread* locking_thread, ObjectMonitorContentionMark& contention_mark) { + // Used by LightweightSynchronizer::inflate_and_enter in deoptimization path to enter for another thread. + // The monitor is private to or already owned by locking_thread which must be suspended. + // So this code may only contend with deflation. + assert(locking_thread == Thread::current() || locking_thread->is_obj_deopt_suspend(), "must be"); + bool success = TryLockWithContentionMark(locking_thread, contention_mark); + assert(success, "Failed to enter_for: locking_thread=" INTPTR_FORMAT - ", this=" INTPTR_FORMAT "{owner=" INTPTR_FORMAT "}, observed owner: " INTPTR_FORMAT, - p2i(locking_thread), p2i(this), p2i(owner_raw()), p2i(prev_owner)); + ", this=" INTPTR_FORMAT "{owner=" INTPTR_FORMAT "}", + p2i(locking_thread), p2i(this), p2i(owner_raw())); } bool ObjectMonitor::enter_for(JavaThread* locking_thread) { + // Used by ObjectSynchronizer::enter_for() to enter for another thread. + // The monitor is private to or already owned by locking_thread which must be suspended. + // So this code may only contend with deflation. + assert(locking_thread == Thread::current() || locking_thread->is_obj_deopt_suspend(), "must be"); // Block out deflation as soon as possible. ObjectMonitorContentionMark contention_mark(this); @@ -375,19 +379,29 @@ bool ObjectMonitor::enter_for(JavaThread* locking_thread) { return false; } - enter_for_with_contention_mark(locking_thread, contention_mark); + bool success = TryLockWithContentionMark(locking_thread, contention_mark); + + assert(success, "Failed to enter_for: locking_thread=" INTPTR_FORMAT + ", this=" INTPTR_FORMAT "{owner=" INTPTR_FORMAT "}", + p2i(locking_thread), p2i(this), p2i(owner_raw())); assert(owner_raw() == locking_thread, "must be"); return true; } -bool ObjectMonitor::try_enter(JavaThread* current) { - // TryLock avoids the CAS +bool ObjectMonitor::try_enter(JavaThread* current, bool check_for_recursion) { + // TryLock avoids the CAS and handles deflation. TryLockResult r = TryLock(current); if (r == TryLockResult::Success) { assert(_recursions == 0, "invariant"); return true; } + // If called from SharedRuntime::monitor_exit_helper(), we know that + // this thread doesn't already own the lock. + if (!check_for_recursion) { + return false; + } + if (r == TryLockResult::HasOwner && owner() == current) { _recursions++; return true; @@ -400,7 +414,6 @@ bool ObjectMonitor::try_enter(JavaThread* current) { set_owner_from_BasicLock(cur, current); // Convert from BasicLock* to Thread*. return true; } - return false; } @@ -561,16 +574,40 @@ void ObjectMonitor::enter_with_contention_mark(JavaThread *current, ObjectMonito ObjectMonitor::TryLockResult ObjectMonitor::TryLock(JavaThread* current) { void* own = owner_raw(); - if (own != nullptr) return TryLockResult::HasOwner; - if (try_set_owner_from(nullptr, current) == nullptr) { - assert(_recursions == 0, "invariant"); - return TryLockResult::Success; + void* first_own = own; + + for (;;) { + if (own == DEFLATER_MARKER) { + // Block out deflation as soon as possible. + ObjectMonitorContentionMark contention_mark(this); + + // Check for deflation. + if (enter_is_async_deflating()) { + // Treat deflation as interference. + return TryLockResult::Interference; + } + if (TryLockWithContentionMark(current, contention_mark)) { + assert(_recursions == 0, "invariant"); + return TryLockResult::Success; + } else { + // Deflation won or change of owner; dont spin + break; + } + } else if (own == nullptr) { + void* prev_own = try_set_owner_from(nullptr, current); + if (prev_own == nullptr) { + assert(_recursions == 0, "invariant"); + return TryLockResult::Success; + } else { + // The lock had been free momentarily, but we lost the race to the lock. + own = prev_own; + } + } else { + // Retry doesn't make as much sense because the lock was just acquired. + break; + } } - // The lock had been free momentarily, but we lost the race to the lock. - // Interference -- the CAS failed. - // We can either return -1 or retry. - // Retry doesn't make as much sense because the lock was just acquired. - return TryLockResult::Interference; + return first_own == own ? TryLockResult::HasOwner : TryLockResult::Interference; } // Deflate the specified ObjectMonitor if not in-use. Returns true if it @@ -746,8 +783,6 @@ const char* ObjectMonitor::is_busy_to_string(stringStream* ss) { return ss->base(); } -#define MAX_RECHECK_INTERVAL 1000 - void ObjectMonitor::EnterI(JavaThread* current) { assert(current->thread_state() == _thread_blocked, "invariant"); @@ -755,25 +790,6 @@ void ObjectMonitor::EnterI(JavaThread* current) { if (TryLock(current) == TryLockResult::Success) { assert(_succ != current, "invariant"); assert(owner_raw() == current, "invariant"); - assert(_Responsible != current, "invariant"); - return; - } - - if (try_set_owner_from(DEFLATER_MARKER, current) == DEFLATER_MARKER) { - // Cancelled the in-progress async deflation by changing owner from - // DEFLATER_MARKER to current. As part of the contended enter protocol, - // contentions was incremented to a positive value before EnterI() - // was called and that prevents the deflater thread from winning the - // last part of the 2-part async deflation protocol. After EnterI() - // returns to enter(), contentions is decremented because the caller - // now owns the monitor. We bump contentions an extra time here to - // prevent the deflater thread from winning the last part of the - // 2-part async deflation protocol after the regular decrement - // occurs in enter(). The deflater thread will decrement contentions - // after it recognizes that the async deflation was cancelled. - add_to_contentions(1); - assert(_succ != current, "invariant"); - assert(_Responsible != current, "invariant"); return; } @@ -789,14 +805,12 @@ void ObjectMonitor::EnterI(JavaThread* current) { if (TrySpin(current)) { assert(owner_raw() == current, "invariant"); assert(_succ != current, "invariant"); - assert(_Responsible != current, "invariant"); return; } // The Spin failed -- Enqueue and park the thread ... assert(_succ != current, "invariant"); assert(owner_raw() != current, "invariant"); - assert(_Responsible != current, "invariant"); // Enqueue "current" on ObjectMonitor's _cxq. // @@ -826,40 +840,10 @@ void ObjectMonitor::EnterI(JavaThread* current) { if (TryLock(current) == TryLockResult::Success) { assert(_succ != current, "invariant"); assert(owner_raw() == current, "invariant"); - assert(_Responsible != current, "invariant"); return; } } - // Check for cxq|EntryList edge transition to non-null. This indicates - // the onset of contention. While contention persists exiting threads - // will use a ST:MEMBAR:LD 1-1 exit protocol. When contention abates exit - // operations revert to the faster 1-0 mode. This enter operation may interleave - // (race) a concurrent 1-0 exit operation, resulting in stranding, so we - // arrange for one of the contending thread to use a timed park() operations - // to detect and recover from the race. (Stranding is form of progress failure - // where the monitor is unlocked but all the contending threads remain parked). - // That is, at least one of the contended threads will periodically poll _owner. - // One of the contending threads will become the designated "Responsible" thread. - // The Responsible thread uses a timed park instead of a normal indefinite park - // operation -- it periodically wakes and checks for and recovers from potential - // strandings admitted by 1-0 exit operations. We need at most one Responsible - // thread per-monitor at any given moment. Only threads on cxq|EntryList may - // be responsible for a monitor. - // - // Currently, one of the contended threads takes on the added role of "Responsible". - // A viable alternative would be to use a dedicated "stranding checker" thread - // that periodically iterated over all the threads (or active monitors) and unparked - // successors where there was risk of stranding. This would help eliminate the - // timer scalability issues we see on some platforms as we'd only have one thread - // -- the checker -- parked on a timer. - - if (nxt == nullptr && _EntryList == nullptr) { - // Try to assume the role of responsible thread for the monitor. - // CONSIDER: ST vs CAS vs { if (Responsible==null) Responsible=current } - Atomic::replace_if_null(&_Responsible, current); - } - // The lock might have been released while this thread was occupied queueing // itself onto _cxq. To close the race and avoid "stranding" and // progress-liveness failure we must resample-retry _owner before parking. @@ -871,8 +855,6 @@ void ObjectMonitor::EnterI(JavaThread* current) { // to defer the state transitions until absolutely necessary, // and in doing so avoid some transitions ... - int recheckInterval = 1; - for (;;) { if (TryLock(current) == TryLockResult::Success) { @@ -881,37 +863,12 @@ void ObjectMonitor::EnterI(JavaThread* current) { assert(owner_raw() != current, "invariant"); // park self - if (_Responsible == current) { - current->_ParkEvent->park((jlong) recheckInterval); - // Increase the recheckInterval, but clamp the value. - recheckInterval *= 8; - if (recheckInterval > MAX_RECHECK_INTERVAL) { - recheckInterval = MAX_RECHECK_INTERVAL; - } - } else { - current->_ParkEvent->park(); - } + current->_ParkEvent->park(); if (TryLock(current) == TryLockResult::Success) { break; } - if (try_set_owner_from(DEFLATER_MARKER, current) == DEFLATER_MARKER) { - // Cancelled the in-progress async deflation by changing owner from - // DEFLATER_MARKER to current. As part of the contended enter protocol, - // contentions was incremented to a positive value before EnterI() - // was called and that prevents the deflater thread from winning the - // last part of the 2-part async deflation protocol. After EnterI() - // returns to enter(), contentions is decremented because the caller - // now owns the monitor. We bump contentions an extra time here to - // prevent the deflater thread from winning the last part of the - // 2-part async deflation protocol after the regular decrement - // occurs in enter(). The deflater thread will decrement contentions - // after it recognizes that the async deflation was cancelled. - add_to_contentions(1); - break; - } - // The lock is still contested. // Keep a tally of the # of futile wakeups. @@ -953,44 +910,23 @@ void ObjectMonitor::EnterI(JavaThread* current) { assert(owner_raw() == current, "invariant"); UnlinkAfterAcquire(current, &node); - if (_succ == current) _succ = nullptr; - - assert(_succ != current, "invariant"); - if (_Responsible == current) { - _Responsible = nullptr; - OrderAccess::fence(); // Dekker pivot-point - - // We may leave threads on cxq|EntryList without a designated - // "Responsible" thread. This is benign. When this thread subsequently - // exits the monitor it can "see" such preexisting "old" threads -- - // threads that arrived on the cxq|EntryList before the fence, above -- - // by LDing cxq|EntryList. Newly arrived threads -- that is, threads - // that arrive on cxq after the ST:MEMBAR, above -- will set Responsible - // non-null and elect a new "Responsible" timer thread. - // - // This thread executes: - // ST Responsible=null; MEMBAR (in enter epilogue - here) - // LD cxq|EntryList (in subsequent exit) - // - // Entering threads in the slow/contended path execute: - // ST cxq=nonnull; MEMBAR; LD Responsible (in enter prolog) - // The (ST cxq; MEMBAR) is accomplished with CAS(). - // - // The MEMBAR, above, prevents the LD of cxq|EntryList in the subsequent - // exit operation from floating above the ST Responsible=null. + if (_succ == current) { + _succ = nullptr; + // Note that we don't need to do OrderAccess::fence() after clearing + // _succ here, since we own the lock. } // We've acquired ownership with CAS(). // CAS is serializing -- it has MEMBAR/FENCE-equivalent semantics. // But since the CAS() this thread may have also stored into _succ, - // EntryList, cxq or Responsible. These meta-data updates must be + // EntryList or cxq. These meta-data updates must be // visible __before this thread subsequently drops the lock. // Consider what could occur if we didn't enforce this constraint -- // STs to monitor meta-data and user-data could reorder with (become // visible after) the ST in exit that drops ownership of the lock. // Some other thread could then acquire the lock, but observe inconsistent // or old monitor meta-data and heap data. That violates the JMM. - // To that end, the 1-0 exit() operation must have at least STST|LDST + // To that end, the exit() operation must have at least STST|LDST // "release" barrier semantics. Specifically, there must be at least a // STST|LDST barrier in exit() before the ST of null into _owner that drops // the lock. The barrier ensures that changes to monitor meta-data and data @@ -1000,8 +936,7 @@ void ObjectMonitor::EnterI(JavaThread* current) { // // Critically, any prior STs to _succ or EntryList must be visible before // the ST of null into _owner in the *subsequent* (following) corresponding - // monitorexit. Recall too, that in 1-0 mode monitorexit does not necessarily - // execute a serializing instruction. + // monitorexit. return; } @@ -1174,39 +1109,32 @@ void ObjectMonitor::UnlinkAfterAcquire(JavaThread* current, ObjectWaiter* curren // In that case exit() is called with _thread_state == _thread_blocked, // but the monitor's _contentions field is > 0, which inhibits reclamation. // -// 1-0 exit -// ~~~~~~~~ -// ::exit() uses a canonical 1-1 idiom with a MEMBAR although some of -// the fast-path operators have been optimized so the common ::exit() -// operation is 1-0, e.g., see macroAssembler_x86.cpp: fast_unlock(). -// The code emitted by fast_unlock() elides the usual MEMBAR. This -// greatly improves latency -- MEMBAR and CAS having considerable local -// latency on modern processors -- but at the cost of "stranding". Absent the -// MEMBAR, a thread in fast_unlock() can race a thread in the slow -// ::enter() path, resulting in the entering thread being stranding -// and a progress-liveness failure. Stranding is extremely rare. -// We use timers (timed park operations) & periodic polling to detect -// and recover from stranding. Potentially stranded threads periodically -// wake up and poll the lock. See the usage of the _Responsible variable. +// This is the exit part of the locking protocol, often implemented in +// C2_MacroAssembler::fast_unlock() +// +// 1. A release barrier ensures that changes to monitor meta-data +// (_succ, _EntryList, _cxq) and data protected by the lock will be +// visible before we release the lock. +// 2. Release the lock by clearing the owner. +// 3. A storeload MEMBAR is needed between releasing the owner and +// subsequently reading meta-data to safely determine if the lock is +// contended (step 4) without an elected successor (step 5). +// 4. If both _EntryList and _cxq are null, we are done, since there is no +// other thread waiting on the lock to wake up. I.e. there is no +// contention. +// 5. If there is a successor (_succ is non-null), we are done. The +// responsibility for guaranteeing progress-liveness has now implicitly +// been moved from the exiting thread to the successor. +// 6. There are waiters in the entry list (_EntryList and/or cxq are +// non-null), but there is no successor (_succ is null), so we need to +// wake up (unpark) a waiting thread to avoid stranding. // -// The CAS() in enter provides for safety and exclusion, while the CAS or -// MEMBAR in exit provides for progress and avoids stranding. 1-0 locking -// eliminates the CAS/MEMBAR from the exit path, but it admits stranding. -// We detect and recover from stranding with timers. +// Note that since only the current lock owner can manipulate the _EntryList +// or drain _cxq, we need to reacquire the lock before we can wake up +// (unpark) a waiting thread. // -// If a thread transiently strands it'll park until (a) another -// thread acquires the lock and then drops the lock, at which time the -// exiting thread will notice and unpark the stranded thread, or, (b) -// the timer expires. If the lock is high traffic then the stranding latency -// will be low due to (a). If the lock is low traffic then the odds of -// stranding are lower, although the worst-case stranding latency -// is longer. Critically, we don't want to put excessive load in the -// platform's timer subsystem. We want to minimize both the timer injection -// rate (timers created/sec) as well as the number of timers active at -// any one time. (more precisely, we want to minimize timer-seconds, which is -// the integral of the # of active timers at any instant over time). -// Both impinge on OS scalability. Given that, at most one thread parked on -// a monitor will use a timer. +// The CAS() in enter provides for safety and exclusion, while the +// MEMBAR in exit provides for progress and avoids stranding. // // There is also the risk of a futile wake-up. If we drop the lock // another thread can reacquire the lock immediately, and we can @@ -1248,10 +1176,6 @@ void ObjectMonitor::exit(JavaThread* current, bool not_suspended) { return; } - // Invariant: after setting Responsible=null an thread must execute - // a MEMBAR or other serializing instruction before fetching EntryList|cxq. - _Responsible = nullptr; - #if INCLUDE_JFR // get the owner's thread id for the MonitorEnter event // if it is enabled and the thread isn't suspended @@ -1278,14 +1202,15 @@ void ObjectMonitor::exit(JavaThread* current, bool not_suspended) { // Other threads are blocked trying to acquire the lock. // Normally the exiting thread is responsible for ensuring succession, - // but if other successors are ready or other entering threads are spinning - // then this thread can simply store null into _owner and exit without - // waking a successor. The existence of spinners or ready successors - // guarantees proper succession (liveness). Responsibility passes to the - // ready or running successors. The exiting thread delegates the duty. - // More precisely, if a successor already exists this thread is absolved - // of the responsibility of waking (unparking) one. - // + // but if this thread observes other successors are ready or other + // entering threads are spinning after it has stored null into _owner + // then it can exit without waking a successor. The existence of + // spinners or ready successors guarantees proper succession (liveness). + // Responsibility passes to the ready or running successors. The exiting + // thread delegates the duty. More precisely, if a successor already + // exists this thread is absolved of the responsibility of waking + // (unparking) one. + // The _succ variable is critical to reducing futile wakeup frequency. // _succ identifies the "heir presumptive" thread that has been made // ready (unparked) but that has not yet run. We need only one such @@ -1296,24 +1221,20 @@ void ObjectMonitor::exit(JavaThread* current, bool not_suspended) { // Note that spinners in Enter() also set _succ non-null. // In the current implementation spinners opportunistically set // _succ so that exiting threads might avoid waking a successor. - // Another less appealing alternative would be for the exiting thread - // to drop the lock and then spin briefly to see if a spinner managed - // to acquire the lock. If so, the exiting thread could exit - // immediately without waking a successor, otherwise the exiting - // thread would need to dequeue and wake a successor. - // (Note that we'd need to make the post-drop spin short, but no - // shorter than the worst-case round-trip cache-line migration time. - // The dropped lock needs to become visible to the spinner, and then - // the acquisition of the lock by the spinner must become visible to - // the exiting thread). + // Which means that the exiting thread could exit immediately without + // waking a successor, if it observes a successor after it has dropped + // the lock. Note that the dropped lock needs to become visible to the + // spinner. // It appears that an heir-presumptive (successor) must be made ready. // Only the current lock owner can manipulate the EntryList or // drain _cxq, so we need to reacquire the lock. If we fail // to reacquire the lock the responsibility for ensuring succession // falls to the new owner. - // - if (try_set_owner_from(nullptr, current) != nullptr) { + + if (TryLock(current) != TryLockResult::Success) { + // Some other thread acquired the lock (or the monitor was + // deflated). Either way we are done. return; } @@ -1376,7 +1297,7 @@ void ObjectMonitor::exit(JavaThread* current, bool not_suspended) { q = p; } - // In 1-0 mode we need: ST EntryList; MEMBAR #storestore; ST _owner = nullptr + // We need to: ST EntryList; MEMBAR #storestore; ST _owner = nullptr // The MEMBAR is satisfied by the release_store() operation in ExitEpilog(). // See if we can abdicate to a spinner instead of waking a thread. @@ -1566,8 +1487,6 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { AddWaiter(&node); Thread::SpinRelease(&_WaitSetLock); - _Responsible = nullptr; - intx save = _recursions; // record the old recursion count _waiters++; // increment the number of waiters _recursions = 0; // set the recursion level to be 1 @@ -2245,7 +2164,6 @@ void ObjectMonitor::print() const { print_on(tty); } // _EntryList = 0x0000000000000000 // _cxq = 0x0000000000000000 // _succ = 0x0000000000000000 -// _Responsible = 0x0000000000000000 // _SpinDuration = 5000 // _contentions = 0 // _WaitSet = 0x0000700009756248 @@ -2274,7 +2192,6 @@ void ObjectMonitor::print_debug_style_on(outputStream* st) const { st->print_cr(" _EntryList = " INTPTR_FORMAT, p2i(_EntryList)); st->print_cr(" _cxq = " INTPTR_FORMAT, p2i(_cxq)); st->print_cr(" _succ = " INTPTR_FORMAT, p2i(_succ)); - st->print_cr(" _Responsible = " INTPTR_FORMAT, p2i(_Responsible)); st->print_cr(" _SpinDuration = %d", _SpinDuration); st->print_cr(" _contentions = %d", contentions()); st->print_cr(" _WaitSet = " INTPTR_FORMAT, p2i(_WaitSet)); diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index ef85559c2b6c3..30d2e5094162d 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -179,7 +179,6 @@ class ObjectMonitor : public CHeapObj { ObjectWaiter* volatile _cxq; // LL of recently-arrived threads blocked on entry. JavaThread* volatile _succ; // Heir presumptive thread - used for futile wakeup throttling - JavaThread* volatile _Responsible; volatile int _SpinDuration; @@ -348,7 +347,7 @@ class ObjectMonitor : public CHeapObj { void enter_for_with_contention_mark(JavaThread* locking_thread, ObjectMonitorContentionMark& contention_mark); bool enter_for(JavaThread* locking_thread); bool enter(JavaThread* current); - bool try_enter(JavaThread* current); + bool try_enter(JavaThread* current, bool check_for_recursion = true); bool spin_enter(JavaThread* current); void enter_with_contention_mark(JavaThread* current, ObjectMonitorContentionMark& contention_mark); void exit(JavaThread* current, bool not_suspended = true); @@ -377,6 +376,7 @@ class ObjectMonitor : public CHeapObj { enum class TryLockResult { Interference = -1, HasOwner = 0, Success = 1 }; + bool TryLockWithContentionMark(JavaThread* locking_thread, ObjectMonitorContentionMark& contention_mark); TryLockResult TryLock(JavaThread* current); bool TrySpin(JavaThread* current); @@ -395,12 +395,17 @@ class ObjectMonitorContentionMark : StackObj { DEBUG_ONLY(friend class ObjectMonitor;) ObjectMonitor* _monitor; + bool _extended; NONCOPYABLE(ObjectMonitorContentionMark); public: explicit ObjectMonitorContentionMark(ObjectMonitor* monitor); ~ObjectMonitorContentionMark(); + + // Extends the contention scope beyond this objects lifetime. + // Requires manual decrement of the contentions counter. + void extend(); }; #endif // SHARE_RUNTIME_OBJECTMONITOR_HPP diff --git a/src/hotspot/share/runtime/objectMonitor.inline.hpp b/src/hotspot/share/runtime/objectMonitor.inline.hpp index d26c459b1b415..6d3c6ff24c38b 100644 --- a/src/hotspot/share/runtime/objectMonitor.inline.hpp +++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp @@ -206,15 +206,32 @@ inline void ObjectMonitor::set_next_om(ObjectMonitor* new_value) { Atomic::store(&_next_om, new_value); } +// Block out deflation. inline ObjectMonitorContentionMark::ObjectMonitorContentionMark(ObjectMonitor* monitor) - : _monitor(monitor) { + : _monitor(monitor), _extended(false) { + // Contentions is incremented to a positive value as part of the + // contended enter protocol, which prevents the deflater thread from + // winning the last part of the 2-part async deflation + // protocol. See: ObjectMonitor::deflate_monitor() and + // ObjectMonitor::TryLockWithContentionMark(). _monitor->add_to_contentions(1); } inline ObjectMonitorContentionMark::~ObjectMonitorContentionMark() { + // Decrement contentions when the contention mark goes out of + // scope. This opens up for deflation, if the contention mark + // hasn't been extended. _monitor->add_to_contentions(-1); } +inline void ObjectMonitorContentionMark::extend() { + // Used by ObjectMonitor::TryLockWithContentionMark() to "extend the + // lifetime" of the contention mark. + assert(!_extended, "extending twice is probably a bad design"); + _monitor->add_to_contentions(1); + _extended = true; +} + inline oop ObjectMonitor::object_peek() const { if (_object.is_null()) { return nullptr; diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 6ca7f42e038f5..e4d4e6aea0f8c 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1963,6 +1963,26 @@ void SharedRuntime::monitor_exit_helper(oopDesc* obj, BasicLock* lock, JavaThrea assert(JavaThread::current() == current, "invariant"); // Exit must be non-blocking, and therefore no exceptions can be thrown. ExceptionMark em(current); + + // Check if C2_MacroAssembler::fast_unlock() or + // C2_MacroAssembler::fast_unlock_lightweight() unlocked an inflated + // monitor before going slow path. Since there is no safepoint + // polling when calling into the VM, we can be sure that the monitor + // hasn't been deallocated. + ObjectMonitor* m = current->unlocked_inflated_monitor(); + if (m != nullptr) { + assert(m->owner_raw() != current, "must be"); + current->clear_unlocked_inflated_monitor(); + + // We need to reacquire the lock before we can call ObjectSynchronizer::exit(). + if (!m->try_enter(current, /*check_for_recursion*/ false)) { + // Some other thread acquired the lock (or the monitor was + // deflated). Either way we are done. + current->dec_held_monitor_count(); + return; + } + } + // The object could become unlocked through a JNI call, which we have no other checks for. // Give a fatal message if CheckJNICalls. Otherwise we ignore it. if (obj->is_unlocked()) { diff --git a/test/micro/org/openjdk/bench/vm/lang/LockUnlock.java b/test/micro/org/openjdk/bench/vm/lang/LockUnlock.java index 3ed862e8218cd..39c8569532ec4 100644 --- a/test/micro/org/openjdk/bench/vm/lang/LockUnlock.java +++ b/test/micro/org/openjdk/bench/vm/lang/LockUnlock.java @@ -309,10 +309,11 @@ private synchronized int fact(int n) { } /** - * With two threads lockObject1 will be contended so should be - * inflated. + * With three threads lockObject1 will be contended so should be + * inflated. Three threads is also needed to ensure a high level + * of code coverage in the locking code. */ - @Threads(2) + @Threads(3) @Benchmark public void testContendedLock() { synchronized (lockObject1) { From cff420d8d3cfbbb729ee47b00c8fe38e410eab1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eirik=20Bj=C3=B8rsn=C3=B8s?= Date: Mon, 30 Sep 2024 13:06:49 +0000 Subject: [PATCH 13/15] 8339711: ZipFile.Source.initCEN needlessly reads END header Reviewed-by: lancea, jpai, redestad --- .../share/classes/java/util/zip/ZipFile.java | 21 +++++++++++-------- .../util/zip/ZipFile/CenSizeTooLarge.java | 4 +++- .../util/zip/ZipFile/EndOfCenValidation.java | 6 ++++-- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/java.base/share/classes/java/util/zip/ZipFile.java b/src/java.base/share/classes/java/util/zip/ZipFile.java index d54e6c1e4fcb9..43b2261f1c60a 100644 --- a/src/java.base/share/classes/java/util/zip/ZipFile.java +++ b/src/java.base/share/classes/java/util/zip/ZipFile.java @@ -63,6 +63,7 @@ import jdk.internal.access.JavaUtilZipFileAccess; import jdk.internal.access.JavaUtilJarAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.util.ArraysSupport; import jdk.internal.util.OperatingSystem; import jdk.internal.perf.PerfCounter; import jdk.internal.ref.CleanerFactory; @@ -1178,6 +1179,8 @@ private static class Source { // "META-INF/".length() private static final int META_INF_LEN = 9; private static final int[] EMPTY_META_VERSIONS = new int[0]; + // CEN size is limited to the maximum array size in the JDK + private static final int MAX_CEN_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH; private final Key key; // the key in files private final @Stable ZipCoder zc; // ZIP coder used to decode/encode @@ -1185,7 +1188,7 @@ private static class Source { private int refs = 1; private RandomAccessFile zfile; // zfile of the underlying ZIP file - private byte[] cen; // CEN & ENDHDR + private byte[] cen; // CEN private long locpos; // position of first LOC header (usually 0) private byte[] comment; // ZIP file comment // list of meta entries in META-INF dir @@ -1241,7 +1244,7 @@ private int checkAndAddEntry(int pos, int index) // should not exceed 65,535 bytes per the PKWare APP.NOTE // 4.4.10, 4.4.11, & 4.4.12. Also check that current CEN header will // not exceed the length of the CEN array - if (headerSize > 0xFFFF || pos + headerSize > cen.length - ENDHDR) { + if (headerSize > 0xFFFF || pos + headerSize > cen.length) { zerror("invalid CEN header (bad header size)"); } @@ -1294,7 +1297,7 @@ private void checkExtraFields(int cenPos, int startingOffset, } // CEN Offset where this Extra field ends int extraEndOffset = startingOffset + extraFieldLen; - if (extraEndOffset > cen.length - ENDHDR) { + if (extraEndOffset > cen.length) { zerror("Invalid CEN header (extra data field size too long)"); } int currentOffset = startingOffset; @@ -1732,12 +1735,12 @@ private void initCEN(int knownTotal) throws IOException { if (locpos < 0) { zerror("invalid END header (bad central directory offset)"); } - // read in the CEN and END - if (end.cenlen + ENDHDR >= Integer.MAX_VALUE) { + // read in the CEN + if (end.cenlen > MAX_CEN_SIZE) { zerror("invalid END header (central directory size too large)"); } - cen = this.cen = new byte[(int)(end.cenlen + ENDHDR)]; - if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen + ENDHDR) { + cen = this.cen = new byte[(int)end.cenlen]; + if (readFullyAt(cen, 0, cen.length, cenpos) != end.cenlen) { zerror("read CEN tables failed"); } this.total = end.centot; @@ -1766,7 +1769,7 @@ private void initCEN(int knownTotal) throws IOException { int idx = 0; // Index into the entries array int pos = 0; int entryPos = CENHDR; - int limit = cen.length - ENDHDR; + int limit = cen.length; manifestNum = 0; while (entryPos <= limit) { if (idx >= entriesLength) { @@ -1829,7 +1832,7 @@ private void initCEN(int knownTotal) throws IOException { } else { metaVersions = EMPTY_META_VERSIONS; } - if (pos + ENDHDR != cen.length) { + if (pos != cen.length) { zerror("invalid CEN header (bad header size)"); } } diff --git a/test/jdk/java/util/zip/ZipFile/CenSizeTooLarge.java b/test/jdk/java/util/zip/ZipFile/CenSizeTooLarge.java index 3a5430d0573e8..e3f0b20fce87c 100644 --- a/test/jdk/java/util/zip/ZipFile/CenSizeTooLarge.java +++ b/test/jdk/java/util/zip/ZipFile/CenSizeTooLarge.java @@ -23,10 +23,12 @@ /* @test * @bug 8272746 + * @modules java.base/jdk.internal.util * @summary Verify that ZipFile rejects a ZIP with a CEN size which does not fit in a Java byte array * @run junit CenSizeTooLarge */ +import jdk.internal.util.ArraysSupport; import org.junit.Before; import org.junit.Test; @@ -49,7 +51,7 @@ public class CenSizeTooLarge { public static final int NAME_LENGTH = 10; // Maximum allowed CEN size allowed by the ZipFile implementation - static final int MAX_CEN_SIZE = Integer.MAX_VALUE - ZipFile.ENDHDR - 1; + static final int MAX_CEN_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH; /** * From the APPNOTE.txt specification: diff --git a/test/jdk/java/util/zip/ZipFile/EndOfCenValidation.java b/test/jdk/java/util/zip/ZipFile/EndOfCenValidation.java index 51ed2c28c12c2..ec6542768c58f 100644 --- a/test/jdk/java/util/zip/ZipFile/EndOfCenValidation.java +++ b/test/jdk/java/util/zip/ZipFile/EndOfCenValidation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,12 @@ /* @test * @bug 8272746 + * @modules java.base/jdk.internal.util * @summary Verify that ZipFile rejects files with CEN sizes exceeding the implementation limit * @run testng/othervm EndOfCenValidation */ +import jdk.internal.util.ArraysSupport; import org.testng.annotations.AfterTest; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; @@ -68,7 +70,7 @@ public class EndOfCenValidation { private static final int ENDSIZ = ZipFile.ENDSIZ; // Offset of CEN size field within ENDHDR private static final int ENDOFF = ZipFile.ENDOFF; // Offset of CEN offset field within ENDHDR // Maximum allowed CEN size allowed by ZipFile - private static int MAX_CEN_SIZE = Integer.MAX_VALUE - ENDHDR - 1; + private static int MAX_CEN_SIZE = ArraysSupport.SOFT_MAX_ARRAY_LENGTH; // Expected message when CEN size does not match file size private static final String INVALID_CEN_BAD_SIZE = "invalid END header (bad central directory size)"; From 860d49db22cf352eaf1b3b20fff43d090f0eebc8 Mon Sep 17 00:00:00 2001 From: Ramkumar Sunderbabu Date: Mon, 30 Sep 2024 13:43:40 +0000 Subject: [PATCH 14/15] 8211400: nsk.share.gc.Memory::getArrayLength returns wrong value Reviewed-by: kbarrett, tschatzl --- .../hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java index f5c70671e5e10..244bcf423c5bc 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/gc/Memory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -150,12 +150,9 @@ public static int getReferenceObjectSize() { * @return length of array */ public static int getArrayLength(long memory, long objectSize) { - int referenceSize = getReferenceSize(); int arrayExtraSize = getArrayExtraSize(); - return (int) Math.min( - (memory - arrayExtraSize) / (objectSize + referenceSize), - Integer.MAX_VALUE - ); + return (int) Math.min((memory - arrayExtraSize) / objectSize, + Integer.MAX_VALUE); } /** @@ -166,7 +163,7 @@ public static int getArrayLength(long memory, long objectSize) { * @return size of array */ public static long getArraySize(int length, long objectSize) { - return getObjectExtraSize() + length * (objectSize + getReferenceSize()); + return getArrayExtraSize() + length * objectSize; } /** From f1bf469b4ee07b48b629a126111e307d3cab7fd7 Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Mon, 30 Sep 2024 14:12:01 +0000 Subject: [PATCH 15/15] 8341199: Use ClassFile's new API loadConstant(int) Reviewed-by: liach, redestad --- .../java/lang/invoke/StringConcatFactory.java | 12 ++++++------ .../classes/java/lang/runtime/SwitchBootstraps.java | 2 +- .../classes/jdk/jfr/internal/EventClassBuilder.java | 2 +- .../jdk/jfr/internal/EventInstrumentation.java | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 4fbbec1769364..97848e1fcb3e5 100644 --- a/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -1526,7 +1526,7 @@ public void accept(CodeBuilder cb) { * length = length(this.length, arg0, arg1, ..., argN); */ if (staticConcat) { - cb.ldc(length); + cb.loadConstant(length); } else { cb.aload(thisSlot) .getfield(concatClass, "length", CD_int); @@ -1549,7 +1549,7 @@ public void accept(CodeBuilder cb) { * length -= suffix.length(); */ if (staticConcat) { - cb.ldc(constants[paramCount].length()) + cb.loadConstant(constants[paramCount].length()) .isub() .istore(lengthSlot); } else { @@ -1557,7 +1557,7 @@ public void accept(CodeBuilder cb) { .getfield(concatClass, "constants", CD_Array_String) .dup() .astore(constantsSlot) - .ldc(paramCount) + .loadConstant(paramCount) .aaload() .dup() .astore(suffixSlot) @@ -1572,7 +1572,7 @@ public void accept(CodeBuilder cb) { * buf = newArrayWithSuffix(suffix, length, coder) */ if (staticConcat) { - cb.ldc(constants[paramCount]); + cb.loadConstant(constants[paramCount]); } else { cb.aload(suffixSlot); } @@ -1759,10 +1759,10 @@ public void accept(CodeBuilder cb) { .loadLocal(kind, cb.parameterSlot(i)); if (staticConcat) { - cb.ldc(constants[i - 3]); + cb.loadConstant(constants[i - 3]); } else { cb.aload(constantsSlot) - .ldc(i - 4) + .loadConstant(i - 4) .aaload(); } diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index bfdb76e2ef1b6..f380cf1070d1d 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -659,7 +659,7 @@ private static Consumer generateTypeSwitchSkeleton(Class selecto MethodTypeDesc.of(ConstantDescs.CD_char)); cb.labelBinding(compare); - cb.ldc(integerLabel); + cb.loadConstant(integerLabel); cb.if_icmpne(next); } else if ((caseLabel instanceof Long || caseLabel instanceof Float || diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventClassBuilder.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventClassBuilder.java index 523622084843c..1373c3ca4968f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventClassBuilder.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventClassBuilder.java @@ -84,7 +84,7 @@ private void buildSetMethod(ClassBuilder builder) { int index = 0; for (ValueDescriptor v : fields) { codeBuilder.iload(1); - codeBuilder.ldc(index); + codeBuilder.loadConstant(index); Label notEqual = codeBuilder.newLabel(); codeBuilder.if_icmpne(notEqual); codeBuilder.aload(0); // this diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java index 71dc97d114e2c..d962a535829ef 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java @@ -499,7 +499,7 @@ private void makeInstrumented() { // if (!settingsMethod(eventConfiguration.settingX)) goto fail; codeBuilder.aload(0); getEventConfiguration(codeBuilder); - codeBuilder.ldc(index); + codeBuilder.loadConstant(index); invokevirtual(codeBuilder, TYPE_EVENT_CONFIGURATION, METHOD_EVENT_CONFIGURATION_GET_SETTING); MethodTypeDesc mdesc = MethodTypeDesc.ofDescriptor("(" + sd.paramType().descriptorString() + ")Z"); codeBuilder.checkcast(sd.paramType());