From 781775d73b4dd0b241870be50c921242f561b8a1 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 6 Dec 2023 21:24:56 +0000 Subject: [PATCH 1/7] 8321484: Make TestImplicitlyDeclaredClasses release independent Reviewed-by: vromero --- .../TestImplicitlyDeclaredClasses.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/langtools/jdk/javadoc/doclet/testImplicitlyDeclaredClasses/TestImplicitlyDeclaredClasses.java b/test/langtools/jdk/javadoc/doclet/testImplicitlyDeclaredClasses/TestImplicitlyDeclaredClasses.java index 20cd55e07bc..80b2a0685ff 100644 --- a/test/langtools/jdk/javadoc/doclet/testImplicitlyDeclaredClasses/TestImplicitlyDeclaredClasses.java +++ b/test/langtools/jdk/javadoc/doclet/testImplicitlyDeclaredClasses/TestImplicitlyDeclaredClasses.java @@ -65,7 +65,7 @@ public void test(Path base) throws IOException { .collect(Collectors.joining("\n"))); // TODO: remove preview-related options once "Implicitly Declared // Classes and Instance Main Methods" has been standardized - javadoc("--enable-preview", "--source=22", + javadoc("--enable-preview", "--source=" + Runtime.version().feature(), "-d", base.resolve("out-" + index).toString(), src.toString()); From 82796bdebbf56b98ec97a6d572ed68c2842f60c6 Mon Sep 17 00:00:00 2001 From: Jim Laskey Date: Wed, 6 Dec 2023 21:55:05 +0000 Subject: [PATCH 2/7] 8320570: NegativeArraySizeException decoding >1G UTF8 bytes with non-ascii characters Reviewed-by: rriggs --- .../share/classes/java/lang/String.java | 14 ++-- .../String/CompactString/NegativeSize.java | 75 +++++++++++++++++++ 2 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 test/jdk/java/lang/String/CompactString/NegativeSize.java diff --git a/src/java.base/share/classes/java/lang/String.java b/src/java.base/share/classes/java/lang/String.java index 5869e086191..2245792999a 100644 --- a/src/java.base/share/classes/java/lang/String.java +++ b/src/java.base/share/classes/java/lang/String.java @@ -592,7 +592,7 @@ private String(Charset charset, byte[] bytes, int offset, int length) { this.coder = LATIN1; return; } - byte[] utf16 = new byte[length << 1]; + byte[] utf16 = StringUTF16.newBytesFor(length); StringLatin1.inflate(latin1, 0, utf16, 0, dp); dp = decodeUTF8_UTF16(latin1, sp, length, utf16, dp, true); if (dp != length) { @@ -601,7 +601,7 @@ private String(Charset charset, byte[] bytes, int offset, int length) { this.value = utf16; this.coder = UTF16; } else { // !COMPACT_STRINGS - byte[] dst = new byte[length << 1]; + byte[] dst = StringUTF16.newBytesFor(length); int dp = decodeUTF8_UTF16(bytes, offset, offset + length, dst, 0, true); if (dp != length) { dst = Arrays.copyOf(dst, dp << 1); @@ -622,7 +622,7 @@ private String(Charset charset, byte[] bytes, int offset, int length) { this.value = Arrays.copyOfRange(bytes, offset, offset + length); this.coder = LATIN1; } else { - byte[] dst = new byte[length << 1]; + byte[] dst = StringUTF16.newBytesFor(length); int dp = 0; while (dp < length) { int b = bytes[offset++]; @@ -763,15 +763,15 @@ static String newStringUTF8NoRepl(byte[] bytes, int offset, int length, boolean return new String(dst, LATIN1); } if (dp == 0) { - dst = new byte[length << 1]; + dst = StringUTF16.newBytesFor(length); } else { - byte[] buf = new byte[length << 1]; + byte[] buf = StringUTF16.newBytesFor(length); StringLatin1.inflate(dst, 0, buf, 0, dp); dst = buf; } dp = decodeUTF8_UTF16(bytes, offset, sl, dst, dp, false); } else { // !COMPACT_STRINGS - dst = new byte[length << 1]; + dst = StringUTF16.newBytesFor(length); dp = decodeUTF8_UTF16(bytes, offset, offset + length, dst, 0, false); } if (dp != length) { @@ -1316,7 +1316,7 @@ private static byte[] encodeUTF8(byte coder, byte[] val, boolean doReplace) { } int dp = 0; - byte[] dst = new byte[val.length << 1]; + byte[] dst = StringUTF16.newBytesFor(val.length); for (byte c : val) { if (c < 0) { dst[dp++] = (byte) (0xc0 | ((c & 0xff) >> 6)); diff --git a/test/jdk/java/lang/String/CompactString/NegativeSize.java b/test/jdk/java/lang/String/CompactString/NegativeSize.java new file mode 100644 index 00000000000..a218c5f18f8 --- /dev/null +++ b/test/jdk/java/lang/String/CompactString/NegativeSize.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.nio.charset.StandardCharsets; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String for negative size. + * @requires vm.bits == 64 & os.maxMemory >= 4G + * @run main/othervm -XX:+CompactStrings -Xmx4g NegativeSize + * @run main/othervm -XX:-CompactStrings -Xmx4g NegativeSize + */ + +// In Java8: java.lang.OutOfMemoryError: Java heap space +// In Java9+: was java.lang.NegativeArraySizeException: -1894967266 +public class NegativeSize { + + static byte[] generateData() { + int asciisize = 1_200_000_000; + byte[] nonAscii = "非アスキー".getBytes(); + int nonAsciiSize = nonAscii.length; + // 1 GB + byte[] arr = new byte[asciisize + nonAsciiSize]; + for (int i=0; i Date: Wed, 6 Dec 2023 21:57:05 +0000 Subject: [PATCH 3/7] 8320443: [macos] Test java/awt/print/PrinterJob/PrinterDevice.java fails on macOS Reviewed-by: aivanov, azvegint --- .../classes/sun/lwawt/macosx/CPrinterJob.java | 4 + .../share/classes/sun/print/PSPrinterJob.java | 2 +- .../classes/sun/print/RasterPrinterJob.java | 4 +- .../awt/print/PrinterJob/PrinterDevice.java | 99 ++++++++++++------- 4 files changed, 69 insertions(+), 40 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java index 625494efc99..407af09810c 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CPrinterJob.java @@ -823,6 +823,10 @@ private Rectangle2D printAndGetPageFormatArea(final Printable printable, final G public void run() { synchronized (ret) { try { + Paper paper = pageFormat.getPaper(); + double width = Math.rint(paper.getWidth()); + double height = Math.rint(paper.getHeight()); + setGraphicsConfigInfo(((Graphics2D)graphics).getTransform(), width, height); int pageResult = printable.print( graphics, pageFormat, pageIndex); if (pageResult != Printable.NO_SUCH_PAGE) { diff --git a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java index 18c8a663d8e..8973467fb97 100644 --- a/src/java.desktop/share/classes/sun/print/PSPrinterJob.java +++ b/src/java.desktop/share/classes/sun/print/PSPrinterJob.java @@ -264,7 +264,7 @@ public class PSPrinterJob extends RasterPrinterJob { private AffineTransform mLastTransform; private double xres = PS_XRES; - private double yres = PS_XRES; + private double yres = PS_YRES; /* non-null if printing EPS for Java Plugin */ private EPSPrinter epsPrinter = null; diff --git a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index b7dcba05cb0..0cf9c16f166 100644 --- a/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -2092,8 +2092,8 @@ protected int getNoncollatedCopies() { private AffineTransform defaultDeviceTransform; private PrinterGraphicsConfig pgConfig; - synchronized void setGraphicsConfigInfo(AffineTransform at, - double pw, double ph) { + protected synchronized void setGraphicsConfigInfo(AffineTransform at, + double pw, double ph) { Point2D.Double pt = new Point2D.Double(pw, ph); at.transform(pt, pt); diff --git a/test/jdk/java/awt/print/PrinterJob/PrinterDevice.java b/test/jdk/java/awt/print/PrinterJob/PrinterDevice.java index 41807610588..8e1b30aaf94 100644 --- a/test/jdk/java/awt/print/PrinterJob/PrinterDevice.java +++ b/test/jdk/java/awt/print/PrinterJob/PrinterDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,22 +23,34 @@ /* * - * @bug 4276227 + * @test + * @bug 4276227 8320443 + * @key printer * @summary Checks that the PrinterGraphics is for a Printer GraphicsDevice. * Test doesn't run unless there's a printer on the system. - * @author prr * @run main/othervm PrinterDevice */ -import java.awt.*; -import java.awt.geom.*; -import java.awt.print.*; -import java.io.*; -import javax.print.attribute.*; -import javax.print.attribute.standard.*; +import java.io.File; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.GraphicsDevice; +import java.awt.Rectangle; +import java.awt.geom.AffineTransform; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import javax.print.attribute.HashPrintRequestAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; +import javax.print.attribute.standard.Destination; +import javax.print.attribute.standard.OrientationRequested; public class PrinterDevice implements Printable { + static volatile boolean failed = false; + public static void main(String args[]) throws PrinterException { System.setProperty("java.awt.headless", "true"); @@ -54,39 +66,52 @@ public static void main(String args[]) throws PrinterException { aset.add(OrientationRequested.LANDSCAPE); pj.setPrintable(new PrinterDevice()); pj.print(aset); + if (failed) { + throw new RuntimeException("Test failed but no exception propagated."); + } } public int print(Graphics g, PageFormat pf, int pageIndex) { - if (pageIndex > 0 ) { - return Printable.NO_SUCH_PAGE; - } - - /* Make sure calls to get DeviceConfig, its transforms, - * etc all work without exceptions and as expected */ - Graphics2D g2 = (Graphics2D)g; - GraphicsConfiguration gConfig = g2.getDeviceConfiguration(); - AffineTransform dt = gConfig.getDefaultTransform(); - AffineTransform nt = gConfig.getNormalizingTransform(); - AffineTransform gt = g2.getTransform(); + if (pageIndex > 0) { + return Printable.NO_SUCH_PAGE; + } - System.out.println("Graphics2D transform = " + gt); - System.out.println("Default transform = " + dt); - System.out.println("Normalizing transform = " + nt); + Graphics2D g2 = (Graphics2D)g; + GraphicsConfiguration gConfig = g2.getDeviceConfiguration(); + AffineTransform nt = null; + try { + /* Make sure calls to get DeviceConfig, its transforms, + * etc all work without exceptions and as expected */ + System.out.println("GraphicsConfig="+gConfig); + AffineTransform dt = gConfig.getDefaultTransform(); + System.out.println("Default transform = " + dt); + nt = gConfig.getNormalizingTransform(); + System.out.println("Normalizing transform = " + nt); + AffineTransform gt = g2.getTransform(); + System.out.println("Graphics2D transform = " + gt); + } catch (Exception e) { + failed = true; + System.err.println("Unexpected exception getting transform."); + e.printStackTrace(); + throw e; + } - Rectangle bounds = gConfig.getBounds(); - System.out.println("Bounds = " + bounds); - if (!nt.isIdentity()) { - throw new RuntimeException("Expected Identity transdform"); - } + Rectangle bounds = gConfig.getBounds(); + System.out.println("Bounds = " + bounds); + if (!nt.isIdentity()) { + failed = true; + throw new RuntimeException("Expected Identity transform"); + } - /* Make sure that device really is TYPE_PRINTER */ - GraphicsDevice gd = gConfig.getDevice(); - System.out.println("Printer Device ID = " + gd.getIDstring()); - if (!(gd.getType() == GraphicsDevice.TYPE_PRINTER)) { - throw new RuntimeException("Expected printer device"); - } - System.out.println(" *** "); - System.out.println(""); - return Printable.PAGE_EXISTS; + /* Make sure that device really is TYPE_PRINTER */ + GraphicsDevice gd = gConfig.getDevice(); + System.out.println("Printer Device ID = " + gd.getIDstring()); + if (gd.getType() != GraphicsDevice.TYPE_PRINTER) { + failed = true; + throw new RuntimeException("Expected printer device"); + } + System.out.println(" *** "); + System.out.println(""); + return Printable.PAGE_EXISTS; } } From 50baaf46b71f6d55281043ef185ac277c2db558e Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 6 Dec 2023 21:58:56 +0000 Subject: [PATCH 4/7] 8321013: Parallel: Refactor ObjectStartArray Reviewed-by: tschatzl, sjohanss --- .../share/gc/parallel/objectStartArray.cpp | 142 +++++++++--------- .../share/gc/parallel/objectStartArray.hpp | 137 ++++------------- .../gc/parallel/objectStartArray.inline.hpp | 50 +++--- src/hotspot/share/gc/parallel/psOldGen.cpp | 17 +-- src/hotspot/share/gc/parallel/psOldGen.hpp | 20 +-- .../share/gc/parallel/psParallelCompact.cpp | 14 +- .../share/gc/parallel/psPromotionLAB.cpp | 11 +- .../share/gc/parallel/psPromotionLAB.hpp | 2 +- .../share/gc/serial/tenuredGeneration.cpp | 4 +- src/hotspot/share/gc/shared/cardTable.cpp | 5 - src/hotspot/share/gc/shared/cardTable.hpp | 2 +- 11 files changed, 152 insertions(+), 252 deletions(-) diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp index 804b936393c..f55324f5997 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.cpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp @@ -25,32 +25,21 @@ #include "precompiled.hpp" #include "gc/parallel/objectStartArray.inline.hpp" #include "gc/shared/cardTableBarrierSet.hpp" -#include "memory/allocation.inline.hpp" #include "nmt/memTracker.hpp" #include "oops/oop.inline.hpp" #include "runtime/java.hpp" #include "utilities/align.hpp" -uint ObjectStartArray::_card_shift = 0; -uint ObjectStartArray::_card_size = 0; -uint ObjectStartArray::_card_size_in_words = 0; +static size_t num_bytes_required(MemRegion mr) { + assert(CardTable::is_card_aligned(mr.start()), "precondition"); + assert(CardTable::is_card_aligned(mr.end()), "precondition"); -void ObjectStartArray::initialize_block_size(uint card_shift) { - _card_shift = card_shift; - _card_size = 1 << _card_shift; - _card_size_in_words = _card_size / sizeof(HeapWord); + return mr.word_size() / BOTConstants::card_size_in_words(); } void ObjectStartArray::initialize(MemRegion reserved_region) { - // We're based on the assumption that we use the same - // size blocks as the card table. - assert(_card_size == CardTable::card_size(), "Sanity"); - assert(_card_size <= MaxBlockSize, "block_size must be less than or equal to " UINT32_FORMAT, MaxBlockSize); - // Calculate how much space must be reserved - _reserved_region = reserved_region; - - size_t bytes_to_reserve = reserved_region.word_size() / _card_size_in_words; + size_t bytes_to_reserve = num_bytes_required(reserved_region); assert(bytes_to_reserve > 0, "Sanity"); bytes_to_reserve = @@ -62,91 +51,96 @@ void ObjectStartArray::initialize(MemRegion reserved_region) { if (!backing_store.is_reserved()) { vm_exit_during_initialization("Could not reserve space for ObjectStartArray"); } - MemTracker::record_virtual_memory_type((address)backing_store.base(), mtGC); + MemTracker::record_virtual_memory_type(backing_store.base(), mtGC); // We do not commit any memory initially _virtual_space.initialize(backing_store); - _raw_base = (jbyte*)_virtual_space.low_boundary(); - assert(_raw_base != nullptr, "set from the backing_store"); - - _offset_base = _raw_base - (size_t(reserved_region.start()) >> _card_shift); - - _covered_region.set_start(reserved_region.start()); - _covered_region.set_word_size(0); + assert(_virtual_space.low_boundary() != nullptr, "set from the backing_store"); - _blocks_region.set_start((HeapWord*)_raw_base); - _blocks_region.set_word_size(0); + _offset_base = (uint8_t*)(_virtual_space.low_boundary() - (uintptr_t(reserved_region.start()) >> BOTConstants::log_card_size())); } void ObjectStartArray::set_covered_region(MemRegion mr) { - assert(_reserved_region.contains(mr), "MemRegion outside of reserved space"); - assert(_reserved_region.start() == mr.start(), "Attempt to move covered region"); - - HeapWord* low_bound = mr.start(); - HeapWord* high_bound = mr.end(); - assert((uintptr_t(low_bound) & (_card_size - 1)) == 0, "heap must start at block boundary"); - assert((uintptr_t(high_bound) & (_card_size - 1)) == 0, "heap must end at block boundary"); - - size_t requested_blocks_size_in_bytes = mr.word_size() / _card_size_in_words; + DEBUG_ONLY(_covered_region = mr;) + size_t requested_size = num_bytes_required(mr); // Only commit memory in page sized chunks - requested_blocks_size_in_bytes = - align_up(requested_blocks_size_in_bytes, os::vm_page_size()); + requested_size = align_up(requested_size, os::vm_page_size()); - _covered_region = mr; + size_t current_size = _virtual_space.committed_size(); - size_t current_blocks_size_in_bytes = _blocks_region.byte_size(); + if (requested_size == current_size) { + return; + } - if (requested_blocks_size_in_bytes > current_blocks_size_in_bytes) { + if (requested_size > current_size) { // Expand - size_t expand_by = requested_blocks_size_in_bytes - current_blocks_size_in_bytes; + size_t expand_by = requested_size - current_size; if (!_virtual_space.expand_by(expand_by)) { vm_exit_out_of_memory(expand_by, OOM_MMAP_ERROR, "object start array expansion"); } - // Clear *only* the newly allocated region - memset(_blocks_region.end(), clean_block, expand_by); - } - - if (requested_blocks_size_in_bytes < current_blocks_size_in_bytes) { + } else { // Shrink - size_t shrink_by = current_blocks_size_in_bytes - requested_blocks_size_in_bytes; + size_t shrink_by = current_size - requested_size; _virtual_space.shrink_by(shrink_by); } - - _blocks_region.set_word_size(requested_blocks_size_in_bytes / sizeof(HeapWord)); - - assert(requested_blocks_size_in_bytes % sizeof(HeapWord) == 0, "Block table not expanded in word sized increment"); - assert(requested_blocks_size_in_bytes == _blocks_region.byte_size(), "Sanity"); - assert(block_for_addr(low_bound) == &_raw_base[0], "Checking start of map"); - assert(block_for_addr(high_bound-1) <= &_raw_base[_blocks_region.byte_size()-1], "Checking end of map"); } -void ObjectStartArray::reset() { - memset(_blocks_region.start(), clean_block, _blocks_region.byte_size()); +static void fill_range(uint8_t* start, uint8_t* end, uint8_t v) { + // + 1 for inclusive + memset(start, v, pointer_delta(end, start, sizeof(uint8_t)) + 1); } -bool ObjectStartArray::object_starts_in_range(HeapWord* start_addr, - HeapWord* end_addr) const { - assert(start_addr <= end_addr, - "Range is wrong. start_addr (" PTR_FORMAT ") is after end_addr (" PTR_FORMAT ")", - p2i(start_addr), p2i(end_addr)); - - assert(is_aligned(start_addr, _card_size), "precondition"); - - if (start_addr == end_addr) { - // No objects in empty range. - return false; +void ObjectStartArray::update_for_block_work(HeapWord* blk_start, + HeapWord* blk_end) { + HeapWord* const cur_card_boundary = align_up_by_card_size(blk_start); + uint8_t* const offset_entry = entry_for_addr(cur_card_boundary); + + // The first card holds the actual offset. + *offset_entry = checked_cast(pointer_delta(cur_card_boundary, blk_start)); + + // Check if this block spans over other cards. + uint8_t* const end_entry = entry_for_addr(blk_end - 1); + assert(offset_entry <= end_entry, "inv"); + + if (offset_entry != end_entry) { + // Handling remaining entries. + uint8_t* start_entry_for_region = offset_entry + 1; + for (uint i = 0; i < BOTConstants::N_powers; i++) { + // -1 so that the reach ends in this region and not at the start + // of the next. + uint8_t* reach = offset_entry + BOTConstants::power_to_cards_back(i + 1) - 1; + uint8_t value = checked_cast(BOTConstants::card_size_in_words() + i); + + fill_range(start_entry_for_region, MIN2(reach, end_entry), value); + start_entry_for_region = reach + 1; + + if (reach >= end_entry) { + break; + } + } + assert(start_entry_for_region > end_entry, "Sanity check"); } - jbyte* start_block = block_for_addr(start_addr); - jbyte* end_block = block_for_addr(end_addr - 1); + debug_only(verify_for_block(blk_start, blk_end);) +} - for (jbyte* block = start_block; block <= end_block; block++) { - if (*block != clean_block) { - return true; +void ObjectStartArray::verify_for_block(HeapWord* blk_start, HeapWord* blk_end) const { + assert(is_crossing_card_boundary(blk_start, blk_end), "precondition"); + + const uint8_t* const start_entry = entry_for_addr(align_up_by_card_size(blk_start)); + const uint8_t* const end_entry = entry_for_addr(blk_end - 1); + // Check entries in [start_entry, end_entry] + assert(*start_entry < BOTConstants::card_size_in_words(), "offset entry"); + + for (const uint8_t* i = start_entry + 1; i <= end_entry; ++i) { + const uint8_t prev = *(i-1); + const uint8_t value = *i; + if (prev != value) { + assert(value >= prev, "monotonic"); + size_t n_cards_back = BOTConstants::entry_to_cards_back(value); + assert(start_entry == (i - n_cards_back), "inv"); } } - - return false; } diff --git a/src/hotspot/share/gc/parallel/objectStartArray.hpp b/src/hotspot/share/gc/parallel/objectStartArray.hpp index 06005fc0075..cc310997b4e 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.hpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.hpp @@ -26,6 +26,7 @@ #define SHARE_GC_PARALLEL_OBJECTSTARTARRAY_HPP #include "gc/parallel/psVirtualspace.hpp" +#include "gc/shared/blockOffsetTable.hpp" #include "memory/allocation.hpp" #include "memory/memRegion.hpp" #include "oops/oop.hpp" @@ -36,141 +37,65 @@ // class ObjectStartArray : public CHeapObj { - friend class VerifyObjectStartArrayClosure; - - private: - PSVirtualSpace _virtual_space; - MemRegion _reserved_region; // The committed (old-gen heap) virtual space this object-start-array covers. - MemRegion _covered_region; - MemRegion _blocks_region; - jbyte* _raw_base; - jbyte* _offset_base; - - static uint _card_shift; - static uint _card_size; - static uint _card_size_in_words; - - public: - - enum BlockValueConstants { - clean_block = -1 - }; - - // Maximum size an offset table entry can cover. This maximum is derived from that - // we need an extra bit for possible offsets in the byte for backskip values, leaving 2^7 possible offsets. - // Minimum object alignment is 8 bytes (2^3), so we can at most represent 2^10 offsets within a BOT value. - static const uint MaxBlockSize = 1024; - - // Initialize block size based on card size - static void initialize_block_size(uint card_shift); + DEBUG_ONLY(MemRegion _covered_region;) - static uint card_shift() { - return _card_shift; - } - - static uint card_size() { - return _card_size; - } - static uint card_size_in_words() { - return _card_size_in_words; - } + // BOT array + PSVirtualSpace _virtual_space; - protected: + // Biased array-start of BOT array for fast heap-addr / BOT entry translation + uint8_t* _offset_base; // Mapping from address to object start array entry - jbyte* block_for_addr(void* p) const { + uint8_t* entry_for_addr(const void* const p) const { assert(_covered_region.contains(p), "out of bounds access to object start array"); - jbyte* result = &_offset_base[uintptr_t(p) >> _card_shift]; - assert(_blocks_region.contains(result), - "out of bounds result in byte_for"); + uint8_t* result = &_offset_base[uintptr_t(p) >> BOTConstants::log_card_size()]; return result; } // Mapping from object start array entry to address of first word - HeapWord* addr_for_block(jbyte* p) { - assert(_blocks_region.contains(p), - "out of bounds access to object start array"); - size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); - HeapWord* result = (HeapWord*) (delta << _card_shift); + HeapWord* addr_for_entry(const uint8_t* const p) const { + size_t delta = pointer_delta(p, _offset_base, sizeof(uint8_t)); + HeapWord* result = (HeapWord*) (delta << BOTConstants::log_card_size()); assert(_covered_region.contains(result), "out of bounds accessor from card marking array"); return result; } - // Mapping that includes the derived offset. - // If the block is clean, returns the last address in the covered region. - // If the block is < index 0, returns the start of the covered region. - HeapWord* offset_addr_for_block(jbyte* p) const { - // We have to do this before the assert - if (p < _raw_base) { - return _covered_region.start(); - } - - assert(_blocks_region.contains(p), - "out of bounds access to object start array"); - - if (*p == clean_block) { - return _covered_region.end(); - } + static HeapWord* align_up_by_card_size(HeapWord* const addr) { + return align_up(addr, BOTConstants::card_size()); + } - size_t delta = pointer_delta(p, _offset_base, sizeof(jbyte)); - HeapWord* result = (HeapWord*) (delta << _card_shift); - result += *p; + void update_for_block_work(HeapWord* blk_start, HeapWord* blk_end); - assert(_covered_region.contains(result), - "out of bounds accessor from card marking array"); - - return result; - } + void verify_for_block(HeapWord* blk_start, HeapWord* blk_end) const; public: - - // This method is in lieu of a constructor, so that this class can be - // embedded inline in other classes. void initialize(MemRegion reserved_region); + // Heap old-gen resizing void set_covered_region(MemRegion mr); - void reset(); - - MemRegion covered_region() { return _covered_region; } - -#define assert_covered_region_contains(addr) \ - assert(_covered_region.contains(addr), \ - #addr " (" PTR_FORMAT ") is not in covered region [" PTR_FORMAT ", " PTR_FORMAT "]", \ - p2i(addr), p2i(_covered_region.start()), p2i(_covered_region.end())) - - void allocate_block(HeapWord* p) { - assert_covered_region_contains(p); - jbyte* block = block_for_addr(p); - HeapWord* block_base = addr_for_block(block); - size_t offset = pointer_delta(p, block_base, sizeof(HeapWord*)); - assert(offset < 128, "Sanity"); - // When doing MT offsets, we can't assert this. - //assert(offset > *block, "Found backwards allocation"); - *block = (jbyte)offset; + static bool is_crossing_card_boundary(HeapWord* const blk_start, + HeapWord* const blk_end) { + HeapWord* cur_card_boundary = align_up_by_card_size(blk_start); + // Strictly greater-than, since we check if this block *crosses* card boundary. + return blk_end > cur_card_boundary; } - // Optimized for finding the first object that crosses into - // a given block. The blocks contain the offset of the last - // object in that block. Scroll backwards by one, and the first - // object hit should be at the beginning of the block - inline HeapWord* object_start(HeapWord* addr) const; + // Returns the address of the start of the block reaching into the card containing + // "addr". + inline HeapWord* block_start_reaching_into_card(HeapWord* const addr) const; - bool is_block_allocated(HeapWord* addr) { - assert_covered_region_contains(addr); - jbyte* block = block_for_addr(addr); - return *block != clean_block; + // [blk_start, blk_end) representing a block of memory in the heap. + void update_for_block(HeapWord* blk_start, HeapWord* blk_end) { + if (is_crossing_card_boundary(blk_start, blk_end)) { + update_for_block_work(blk_start, blk_end); + } } - // Return true iff an object starts in - // [start_addr, end_addr_aligned_up) - // where - // end_addr_aligned_up = align_up(end_addr, _card_size) - // Precondition: start_addr is card-size aligned - bool object_starts_in_range(HeapWord* start_addr, HeapWord* end_addr) const; + inline HeapWord* object_start(HeapWord* const addr) const; }; #endif // SHARE_GC_PARALLEL_OBJECTSTARTARRAY_HPP diff --git a/src/hotspot/share/gc/parallel/objectStartArray.inline.hpp b/src/hotspot/share/gc/parallel/objectStartArray.inline.hpp index 75650a6e1cf..3fb6cb61fc1 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.inline.hpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.inline.hpp @@ -27,27 +27,41 @@ #include "gc/parallel/objectStartArray.hpp" -// Optimized for finding the first object that crosses into -// a given block. The blocks contain the offset of the last -// object in that block. Scroll backwards by one, and the first -// object hit should be at the beginning of the block -HeapWord* ObjectStartArray::object_start(HeapWord* addr) const { - assert_covered_region_contains(addr); - jbyte* block = block_for_addr(addr); - HeapWord* scroll_forward = offset_addr_for_block(block--); - while (scroll_forward > addr) { - scroll_forward = offset_addr_for_block(block--); - } +HeapWord* ObjectStartArray::object_start(HeapWord* const addr) const { + HeapWord* cur_block = block_start_reaching_into_card(addr); - HeapWord* next = scroll_forward; - while (next <= addr) { - scroll_forward = next; - next += cast_to_oop(next)->size(); + while (true) { + HeapWord* next_block = cur_block + cast_to_oop(cur_block)->size(); + if (next_block > addr) { + assert(cur_block <= addr, "postcondition"); + return cur_block; + } + // Because the BOT is precise, we should never step into the next card + // (i.e. crossing the card boundary). + assert(!is_crossing_card_boundary(next_block, addr), "must be"); + cur_block = next_block; } - assert(scroll_forward <= addr, "wrong order for current and arg"); - assert(addr <= next, "wrong order for arg and next"); - return scroll_forward; } +HeapWord* ObjectStartArray::block_start_reaching_into_card(HeapWord* const addr) const { + const uint8_t* entry = entry_for_addr(addr); + + uint8_t offset; + while (true) { + offset = *entry; + + if (offset < BOTConstants::card_size_in_words()) { + break; + } + + // The excess of the offset from N_words indicates a power of Base + // to go back by. + size_t n_cards_back = BOTConstants::entry_to_cards_back(offset); + entry -= n_cards_back; + } + + HeapWord* q = addr_for_entry(entry); + return q - offset; +} #endif // SHARE_GC_PARALLEL_OBJECTSTARTARRAY_INLINE_HPP diff --git a/src/hotspot/share/gc/parallel/psOldGen.cpp b/src/hotspot/share/gc/parallel/psOldGen.cpp index 8124f018b28..14be4745b15 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.cpp +++ b/src/hotspot/share/gc/parallel/psOldGen.cpp @@ -92,10 +92,10 @@ void PSOldGen::initialize_work(const char* perf_data_name, int level) { // If this wasn't true, a single card could span more than one generation, // which would cause problems when we commit/uncommit memory, and when we // clear and dirty cards. - guarantee(ct->is_card_aligned(reserved_mr.start()), "generation must be card aligned"); + guarantee(CardTable::is_card_aligned(reserved_mr.start()), "generation must be card aligned"); // Check the heap layout documented at `class ParallelScavengeHeap`. assert(reserved_mr.end() != heap->reserved_region().end(), "invariant"); - guarantee(ct->is_card_aligned(reserved_mr.end()), "generation must be card aligned"); + guarantee(CardTable::is_card_aligned(reserved_mr.end()), "generation must be card aligned"); // // ObjectSpace stuff @@ -133,18 +133,14 @@ size_t PSOldGen::num_iterable_blocks() const { void PSOldGen::object_iterate_block(ObjectClosure* cl, size_t block_index) { size_t block_word_size = IterateBlockSize / HeapWordSize; - assert((block_word_size % (ObjectStartArray::card_size())) == 0, - "Block size not a multiple of start_array block"); + assert((block_word_size % BOTConstants::card_size_in_words()) == 0, + "To ensure fast object_start calls"); MutableSpace *space = object_space(); HeapWord* begin = space->bottom() + block_index * block_word_size; HeapWord* end = MIN2(space->top(), begin + block_word_size); - if (!start_array()->object_starts_in_range(begin, end)) { - return; - } - // Get object starting at or reaching into this block. HeapWord* start = start_array()->object_start(begin); if (start < begin) { @@ -286,8 +282,8 @@ void PSOldGen::shrink(size_t bytes) { void PSOldGen::complete_loaded_archive_space(MemRegion archive_space) { HeapWord* cur = archive_space.start(); while (cur < archive_space.end()) { - _start_array.allocate_block(cur); size_t word_size = cast_to_oop(cur)->size(); + _start_array.update_for_block(cur, cur + word_size); cur += word_size; } } @@ -390,14 +386,13 @@ void PSOldGen::verify() { class VerifyObjectStartArrayClosure : public ObjectClosure { ObjectStartArray* _start_array; - public: +public: VerifyObjectStartArrayClosure(ObjectStartArray* start_array) : _start_array(start_array) { } virtual void do_object(oop obj) { HeapWord* test_addr = cast_from_oop(obj) + 1; guarantee(_start_array->object_start(test_addr) == cast_from_oop(obj), "ObjectStartArray cannot find start of object"); - guarantee(_start_array->is_block_allocated(cast_from_oop(obj)), "ObjectStartArray missing block allocation"); } }; diff --git a/src/hotspot/share/gc/parallel/psOldGen.hpp b/src/hotspot/share/gc/parallel/psOldGen.hpp index c26f251f9a2..4898baa3a44 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.hpp +++ b/src/hotspot/share/gc/parallel/psOldGen.hpp @@ -51,29 +51,11 @@ class PSOldGen : public CHeapObj { // Block size for parallel iteration static const size_t IterateBlockSize = 1024 * 1024; -#ifdef ASSERT - void assert_block_in_covered_region(MemRegion new_memregion) { - // Explicitly capture current covered_region in a local - MemRegion covered_region = this->start_array()->covered_region(); - assert(covered_region.contains(new_memregion), - "new region is not in covered_region [ " PTR_FORMAT ", " PTR_FORMAT " ], " - "new region [ " PTR_FORMAT ", " PTR_FORMAT " ], " - "object space [ " PTR_FORMAT ", " PTR_FORMAT " ]", - p2i(covered_region.start()), - p2i(covered_region.end()), - p2i(new_memregion.start()), - p2i(new_memregion.end()), - p2i(this->object_space()->used_region().start()), - p2i(this->object_space()->used_region().end())); - } -#endif - HeapWord* cas_allocate_noexpand(size_t word_size) { assert_locked_or_safepoint(Heap_lock); HeapWord* res = object_space()->cas_allocate(word_size); if (res != nullptr) { - DEBUG_ONLY(assert_block_in_covered_region(MemRegion(res, word_size))); - _start_array.allocate_block(res); + _start_array.update_for_block(res, res + word_size); } return res; } diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index c966aea5a86..09892208c35 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1496,7 +1496,7 @@ void PSParallelCompact::fill_dense_prefix_end(SpaceId id) _mark_bitmap.mark_obj(obj_beg, obj_len); _summary_data.add_obj(obj_beg, obj_len); assert(start_array(id) != nullptr, "sanity"); - start_array(id)->allocate_block(obj_beg); + start_array(id)->update_for_block(obj_beg, obj_beg + obj_len); } } @@ -2462,7 +2462,6 @@ void PSParallelCompact::compact() { ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); PSOldGen* old_gen = heap->old_gen(); - old_gen->start_array()->reset(); uint active_gc_threads = ParallelScavengeHeap::heap()->workers().active_workers(); // for [0..last_space_id) @@ -2534,7 +2533,7 @@ void PSParallelCompact::verify_complete(SpaceId space_id) { #endif // #ifdef ASSERT inline void UpdateOnlyClosure::do_addr(HeapWord* addr) { - _start_array->allocate_block(addr); + _start_array->update_for_block(addr, addr + cast_to_oop(addr)->size()); compaction_manager()->update_contents(cast_to_oop(addr)); } @@ -2627,7 +2626,7 @@ void PSParallelCompact::update_deferred_object(ParCompactionManager* cm, HeapWor const SpaceInfo* const space_info = _space_info + space_id(addr); ObjectStartArray* const start_array = space_info->start_array(); if (start_array != nullptr) { - start_array->allocate_block(addr); + start_array->update_for_block(addr, addr + cast_to_oop(addr)->size()); } cm->update_contents(cast_to_oop(addr)); @@ -3133,7 +3132,7 @@ MoveAndUpdateClosure::do_addr(HeapWord* addr, size_t words) { // The start_array must be updated even if the object is not moving. if (_start_array != nullptr) { - _start_array->allocate_block(destination()); + _start_array->update_for_block(destination(), destination() + words); } if (copy_destination() != source()) { @@ -3197,8 +3196,9 @@ FillClosure::do_addr(HeapWord* addr, size_t size) { CollectedHeap::fill_with_objects(addr, size); HeapWord* const end = addr + size; do { - _start_array->allocate_block(addr); - addr += cast_to_oop(addr)->size(); + size_t size = cast_to_oop(addr)->size(); + _start_array->update_for_block(addr, addr + size); + addr += size; } while (addr < end); return ParMarkBitMap::incomplete; } diff --git a/src/hotspot/share/gc/parallel/psPromotionLAB.cpp b/src/hotspot/share/gc/parallel/psPromotionLAB.cpp index 7aa1731fd87..4c3367cdf9c 100644 --- a/src/hotspot/share/gc/parallel/psPromotionLAB.cpp +++ b/src/hotspot/share/gc/parallel/psPromotionLAB.cpp @@ -115,7 +115,8 @@ void PSOldPromotionLAB::flush() { assert(_start_array != nullptr, "Sanity"); - _start_array->allocate_block(obj); + // filler obj + _start_array->update_for_block(obj, obj + cast_to_oop(obj)->size()); } #ifdef ASSERT @@ -132,17 +133,11 @@ bool PSYoungPromotionLAB::lab_is_valid(MemRegion lab) { } bool PSOldPromotionLAB::lab_is_valid(MemRegion lab) { - assert(_start_array->covered_region().contains(lab), "Sanity"); - ParallelScavengeHeap* heap = ParallelScavengeHeap::heap(); PSOldGen* old_gen = heap->old_gen(); MemRegion used = old_gen->object_space()->used_region(); - if (used.contains(lab)) { - return true; - } - - return false; + return used.contains(lab); } #endif /* ASSERT */ diff --git a/src/hotspot/share/gc/parallel/psPromotionLAB.hpp b/src/hotspot/share/gc/parallel/psPromotionLAB.hpp index b3c573ec704..e8e42d3754b 100644 --- a/src/hotspot/share/gc/parallel/psPromotionLAB.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionLAB.hpp @@ -120,7 +120,7 @@ class PSOldPromotionLAB : public PSPromotionLAB { set_top(new_top); assert(is_object_aligned(obj) && is_object_aligned(new_top), "checking alignment"); - _start_array->allocate_block(obj); + _start_array->update_for_block(obj, obj + size); return obj; } diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index 981322eb141..ad5fda3aeab 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -303,8 +303,8 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs, // If this wasn't true, a single card could span more than on generation, // which would cause problems when we commit/uncommit memory, and when we // clear and dirty cards. - guarantee(_rs->is_card_aligned(reserved_mr.start()), "generation must be card aligned"); - guarantee(_rs->is_card_aligned(reserved_mr.end()), "generation must be card aligned"); + guarantee(CardTable::is_card_aligned(reserved_mr.start()), "generation must be card aligned"); + guarantee(CardTable::is_card_aligned(reserved_mr.end()), "generation must be card aligned"); _min_heap_delta_bytes = MinHeapDeltaBytes; _capacity_at_prologue = initial_byte_size; _used_at_prologue = 0; diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index a5025a4e5a2..fdf6dcf3ece 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -54,11 +54,6 @@ void CardTable::initialize_card_size() { // Set blockOffsetTable size based on card table entry size BOTConstants::initialize_bot_size(_card_shift); -#if INCLUDE_PARALLELGC - // Set ObjectStartArray block size based on card table entry size - ObjectStartArray::initialize_block_size(_card_shift); -#endif - log_info_p(gc, init)("CardTable entry size: " UINT32_FORMAT, _card_size); } diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index b9a7b516d8b..61858075ca5 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -119,7 +119,7 @@ class CardTable: public CHeapObj { void clear_MemRegion(MemRegion mr); // Return true if "p" is at the start of a card. - bool is_card_aligned(HeapWord* p) { + static bool is_card_aligned(HeapWord* p) { return is_aligned(p, card_size()); } From 91ffdfb1fcacbb95b93491d412e506695198946e Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 6 Dec 2023 21:59:23 +0000 Subject: [PATCH 5/7] 8320365: IPPPrintService.getAttributes() causes blanket re-initialisation Reviewed-by: aivanov, azvegint --- .../classes/sun/print/IPPPrintService.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java index 91be3e06a5a..95a2682e058 100644 --- a/src/java.desktop/unix/classes/sun/print/IPPPrintService.java +++ b/src/java.desktop/unix/classes/sun/print/IPPPrintService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -456,12 +456,14 @@ private void initAttributes() { // IPP currently does not support it but PPD does. try { - cps = new CUPSPrinter(printer); - mediaSizeNames = cps.getMediaSizeNames(); - mediaTrays = cps.getMediaTrays(); - customMediaSizeNames = cps.getCustomMediaSizeNames(); - defaultMediaIndex = cps.getDefaultMediaIndex(); - rawResolutions = cps.getRawResolutions(); + if (cps == null) { + cps = new CUPSPrinter(printer); + mediaSizeNames = cps.getMediaSizeNames(); + mediaTrays = cps.getMediaTrays(); + customMediaSizeNames = cps.getCustomMediaSizeNames(); + defaultMediaIndex = cps.getDefaultMediaIndex(); + rawResolutions = cps.getRawResolutions(); + } urlConnection.disconnect(); init = true; return; @@ -1225,9 +1227,17 @@ T getAttribute(Class category) public synchronized PrintServiceAttributeSet getAttributes() { - // update getAttMap by sending again get-attributes IPP request - init = false; - initAttributes(); + if (!init) { + // get all attributes for the first time. + initAttributes(); + } else { + // only need service attributes updated. + // update getAttMap by sending again get-attributes IPP request + if ((urlConnection = getIPPConnection(myURL)) != null) { + opGetAttributes(); + urlConnection.disconnect(); + } + } HashPrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); From 75a7c199d8a3634b258cd713b8b77e026c2ecb4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Wed, 6 Dec 2023 22:59:26 +0000 Subject: [PATCH 6/7] 8315827: Kitchensink.java and RenaissanceStressTest.java time out with jvmti module errors Reviewed-by: egahlin --- src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp index acf7e3a7722..0ab787a7f3a 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/javaThreadStatus.hpp" #include "jfr/jfrEvents.hpp" #include "jfr/recorder/jfrRecorder.hpp" #include "jfr/periodic/sampling/jfrCallTrace.hpp" @@ -200,7 +201,7 @@ void OSThreadSampler::protected_task(const SuspendedThreadTaskContext& context) ev->set_starttime(_suspend_time); ev->set_endtime(_suspend_time); // fake to not take an end time ev->set_sampledThread(JfrThreadLocal::thread_id(jt)); - ev->set_state(static_cast(java_lang_Thread::get_thread_status(_thread_oop))); + ev->set_state(static_cast(JavaThreadStatus::RUNNABLE)); } } } @@ -230,7 +231,7 @@ static void write_native_event(JfrThreadSampleClosure& closure, JavaThread* jt, EventNativeMethodSample *ev = closure.next_event_native(); ev->set_starttime(JfrTicks::now()); ev->set_sampledThread(JfrThreadLocal::thread_id(jt)); - ev->set_state(static_cast(java_lang_Thread::get_thread_status(thread_oop))); + ev->set_state(static_cast(JavaThreadStatus::RUNNABLE)); } void JfrNativeSamplerCallback::call() { From 632a3c56e0626b4c4f79c8cb3d2ae312668d63fc Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 7 Dec 2023 03:34:49 +0000 Subject: [PATCH 7/7] 8305825: getBounds API returns wrong value resulting in multiple Regression Test Failures on Ubuntu 23.04 Reviewed-by: prr, achung, honkar, aivanov --- .../classes/sun/awt/X11/XDecoratedPeer.java | 3 ++- .../unix/classes/sun/awt/X11/XWM.java | 4 +++ test/jdk/ProblemList.txt | 5 ++-- .../Modal/NestedModalDialogTest.java | 25 +++++++++++-------- .../OwnedWindowFocusIMECrashTest.java | 3 ++- .../MultiResolutionSplashTest.java | 4 ++- .../swing/JRootPane/DefaultButtonTest.java | 5 +++- .../swing/JTree/8003400/Test8003400.java | 6 ++++- 8 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java b/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java index 5942b5957aa..102a76b16a7 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XDecoratedPeer.java @@ -341,7 +341,8 @@ public void handlePropertyNotify(XEvent xev) { || ev.get_atom() == XWM.XA_NET_FRAME_EXTENTS.getAtom()) { if (XWM.getWMID() != XWM.UNITY_COMPIZ_WM) { - if (getMWMDecorTitleProperty().isPresent()) { + if ((XWM.getWMID() == XWM.MUTTER_WM && !isTargetUndecorated() && isVisible()) + || getMWMDecorTitleProperty().isPresent()) { // Insets might have changed "in-flight" if that property // is present, so we need to get the actual values of // insets from the WM and propagate them through all the diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWM.java b/src/java.desktop/unix/classes/sun/awt/X11/XWM.java index 9c18168e1fc..0382a7b6caf 100644 --- a/src/java.desktop/unix/classes/sun/awt/X11/XWM.java +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWM.java @@ -1369,6 +1369,9 @@ Insets guessInsets(XDecoratedPeer window) { case UNITY_COMPIZ_WM: res = new Insets(28, 1, 1, 1); break; + case MUTTER_WM: + res = new Insets(37, 0, 0, 0); + break; case MOTIF_WM: case OPENLOOK_WM: default: @@ -1380,6 +1383,7 @@ Insets guessInsets(XDecoratedPeer window) { } return res; } + /* * Some buggy WMs ignore window gravity when processing * ConfigureRequest and position window as if the gravity is Static. diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 1faa360aacd..94a020585e4 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -458,6 +458,7 @@ java/awt/Graphics2D/DrawString/RotTransText.java 8316878 linux-all java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.java 8257529 windows-x64 java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeForModalDialogTest/ConsumeForModalDialogTest.java 8302787 windows-all java/awt/KeyboardFocusmanager/TypeAhead/MenuItemActivatedTest/MenuItemActivatedTest.java 8302787 windows-all +java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java 8321303 linux-all java/awt/Window/GetScreenLocation/GetScreenLocationTest.java 8225787 linux-x64 java/awt/Dialog/MakeWindowAlwaysOnTop/MakeWindowAlwaysOnTop.java 8266243 macosx-aarch64 @@ -650,6 +651,7 @@ javax/sound/sampled/Clip/ClipIsRunningAfterStop.java 8307574 linux-x64 javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java 8233177 linux-all,windows-all +javax/swing/JFrame/MaximizeWindowTest.java 8321289 linux-all javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedTranslucentPerPixelTranslucentGradient.java 8233582 linux-all javax/swing/JWindow/ShapedAndTranslucentWindows/ShapedPerPixelTranslucentGradient.java 8233582 linux-all javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentSwing.java 8194128 macosx-all @@ -682,9 +684,6 @@ sanity/client/SwingSet/src/EditorPaneDemoTest.java 8212240 linux-x64 # jdk_swing Ubuntu 23.04 specific -javax/swing/JTree/8003400/Test8003400.java 8309734 linux-all -javax/swing/JTable/7124218/SelectEditTableCell.java 8309734 linux-all -javax/swing/JFileChooser/JFileChooserSetLocationTest.java 8309734 linux-all javax/swing/JComboBox/TestComboBoxComponentRendering.java 8309734 linux-all ############################################################################ diff --git a/test/jdk/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java b/test/jdk/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java index f5d85d8a2ad..c7ec4d66000 100644 --- a/test/jdk/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java +++ b/test/jdk/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,12 +54,11 @@ import java.awt.event.KeyEvent; public class NestedModalDialogTest { - private static Frame frame; + private static StartFrame frame; private static IntermediateDialog interDiag; private static TextDialog txtDiag; // Global variables so the robot thread can locate things. - private static Button[] robot_button = new Button[2]; private static TextField robot_text = null; private static Robot robot = null; @@ -78,6 +77,9 @@ private static void blockTillDisplayed(Component comp) { } private static void clickOnComp(Component comp) { + robot.waitForIdle(); + robot.delay(1000); + Rectangle bounds = new Rectangle(comp.getLocationOnScreen(), comp.getSize()); robot.mouseMove(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); robot.waitForIdle(); @@ -94,11 +96,11 @@ public void testModalDialogs() throws Exception { // launch first frame with firstButton frame = new StartFrame(); blockTillDisplayed(frame); - clickOnComp(robot_button[0]); + clickOnComp(frame.button); // Dialog must be created and onscreen before we proceed. blockTillDisplayed(interDiag); - clickOnComp(robot_button[1]); + clickOnComp(interDiag.button); // Again, the Dialog must be created and onscreen before we proceed. blockTillDisplayed(robot_text); @@ -144,6 +146,8 @@ public void testModalDialogs() throws Exception { */ class StartFrame extends Frame { + public volatile Button button; + /** * Constructs a new instance. */ @@ -168,7 +172,7 @@ public void actionPerformed(ActionEvent e) { pan.add(but); add(pan); setVisible(true); - robot_button[0] = but; + button = but; } } @@ -177,6 +181,7 @@ public void actionPerformed(ActionEvent e) { class IntermediateDialog extends Dialog { Dialog m_parent; + public volatile Button button; public IntermediateDialog(Frame parent) { super(parent, "Intermediate Modal", true /*Modal*/); @@ -193,9 +198,7 @@ public void actionPerformed(ActionEvent e) { pan.add(but); add(pan); pack(); - - // The robot needs to know about us, so set global - robot_button[1] = but; + button = but; } } @@ -215,12 +218,12 @@ public TextDialog(Dialog parent) { } } - public static void main(String[] args) throws RuntimeException, Exception { + public static void main(String[] args) throws Exception { try { new NestedModalDialogTest().testModalDialogs(); } catch (Exception e) { throw new RuntimeException("NestedModalDialogTest object creation " - + "failed"); + + "failed", e); } } } diff --git a/test/jdk/java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java b/test/jdk/java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java index 6fe6b6a1fa5..f81b25cb1d4 100644 --- a/test/jdk/java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java +++ b/test/jdk/java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,7 @@ public void start() { window.setVisible(true); Util.waitForIdle(robot); + robot.delay(1000); test(); diff --git a/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java b/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java index 6018d044a61..1f2de081cce 100644 --- a/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java +++ b/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,6 +120,7 @@ static void testSplash(ImageInfo test) throws Exception { static void testFocus() throws Exception { Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); robot.setAutoDelay(50); Frame frame = new Frame(); @@ -130,6 +131,7 @@ static void testFocus() throws Exception { frame.add(textField); frame.setVisible(true); robot.waitForIdle(); + robot.delay(1000); robot.keyPress(KeyEvent.VK_A); robot.keyRelease(KeyEvent.VK_A); diff --git a/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java b/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java index 560c5d82331..784cd00c244 100644 --- a/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java +++ b/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,6 +83,7 @@ private void createUI() { public void runTest() throws Exception { Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); robot.setAutoDelay(100); for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { try { @@ -100,6 +101,8 @@ public void runTest() throws Exception { createUI(); }); robot.waitForIdle(); + robot.delay(1000); + robot.keyPress(KeyEvent.VK_ENTER); robot.keyRelease(KeyEvent.VK_ENTER); robot.waitForIdle(); diff --git a/test/jdk/javax/swing/JTree/8003400/Test8003400.java b/test/jdk/javax/swing/JTree/8003400/Test8003400.java index 95f5e826aa9..dcc9b0fce6e 100644 --- a/test/jdk/javax/swing/JTree/8003400/Test8003400.java +++ b/test/jdk/javax/swing/JTree/8003400/Test8003400.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -109,6 +109,10 @@ public void run() { Robot robot = new Robot(); robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + robot.waitForIdle(); + robot.delay(500); + SwingUtilities.invokeAndWait(() -> { point = tree.getLocationOnScreen(); rect = tree.getBounds();