diff --git a/make/hotspot/lib/JvmOverrideFiles.gmk b/make/hotspot/lib/JvmOverrideFiles.gmk index 63169b4d672..6a513e10c61 100644 --- a/make/hotspot/lib/JvmOverrideFiles.gmk +++ b/make/hotspot/lib/JvmOverrideFiles.gmk @@ -37,6 +37,10 @@ ifeq ($(TOOLCHAIN_TYPE), gcc) # Need extra inlining to collapse shared marking code into the hot marking loop BUILD_LIBJVM_shenandoahMark.cpp_CXXFLAGS := --param inline-unit-growth=1000 endif + # disable lto in g1ParScanThreadState because of special inlining/flattening used there + ifeq ($(call check-jvm-feature, link-time-opt), true) + BUILD_LIBJVM_g1ParScanThreadState.cpp_CXXFLAGS := -fno-lto + endif endif LIBJVM_FDLIBM_COPY_OPT_FLAG := $(CXX_O_FLAG_NONE) diff --git a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp index 8eefcba7ba2..f70450b7222 100644 --- a/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateInterpreterGenerator_aarch64.cpp @@ -620,7 +620,7 @@ address TemplateInterpreterGenerator::generate_cont_resume_interpreter_adapter() // Restore Java expression stack pointer __ ldr(rscratch1, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize)); __ lea(esp, Address(rfp, rscratch1, Address::lsl(Interpreter::logStackElementSize))); - // and NULL it as marker that esp is now tos until next java call + // and null it as marker that esp is now tos until next java call __ str(zr, Address(rfp, frame::interpreter_frame_last_sp_offset * wordSize)); // Restore machine SP diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index ac28f4b3514..2e062cab605 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -552,7 +552,7 @@ address TemplateInterpreterGenerator::generate_cont_resume_interpreter_adapter() // Restore Java expression stack pointer __ ld(t0, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); __ shadd(esp, t0, fp, t0, Interpreter::logStackElementSize); - // and NULL it as marker that esp is now tos until next java call + // and null it as marker that esp is now tos until next java call __ sd(zr, Address(fp, frame::interpreter_frame_last_sp_offset * wordSize)); // Restore machine SP diff --git a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp index beb80d83e2e..823b965a09b 100644 --- a/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp +++ b/src/hotspot/cpu/x86/templateInterpreterGenerator_x86.cpp @@ -400,7 +400,7 @@ address TemplateInterpreterGenerator::generate_cont_resume_interpreter_adapter() // Restore stack bottom __ movptr(rcx, Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize)); __ lea(rsp, Address(rbp, rcx, Address::times_ptr)); - // and NULL it as marker that esp is now tos until next java call + // and null it as marker that esp is now tos until next java call __ movptr(Address(rbp, frame::interpreter_frame_last_sp_offset * wordSize), NULL_WORD); __ jmp(rax); diff --git a/src/hotspot/share/cds/archiveUtils.hpp b/src/hotspot/share/cds/archiveUtils.hpp index 606f5137e9d..ee1135b70fa 100644 --- a/src/hotspot/share/cds/archiveUtils.hpp +++ b/src/hotspot/share/cds/archiveUtils.hpp @@ -162,7 +162,7 @@ class DumpRegion { DumpRegion(const char* name, uintx max_delta = 0) : _name(name), _base(nullptr), _top(nullptr), _end(nullptr), _max_delta(max_delta), _is_packed(false), - _rs(NULL), _vs(NULL) {} + _rs(nullptr), _vs(nullptr) {} char* expand_top_to(char* newtop); char* allocate(size_t num_bytes, size_t alignment = 0); diff --git a/src/hotspot/share/cds/metaspaceShared.cpp b/src/hotspot/share/cds/metaspaceShared.cpp index b2f5f420365..3ea2f54cfa9 100644 --- a/src/hotspot/share/cds/metaspaceShared.cpp +++ b/src/hotspot/share/cds/metaspaceShared.cpp @@ -315,7 +315,7 @@ static GrowableArrayCHeap* _extra_interned_strings = n // Extra Symbols to be added to the archive static GrowableArrayCHeap* _extra_symbols = nullptr; // Methods managed by SystemDictionary::find_method_handle_intrinsic() to be added to the archive -static GrowableArray* _pending_method_handle_intrinsics = NULL; +static GrowableArray* _pending_method_handle_intrinsics = nullptr; void MetaspaceShared::read_extra_data(JavaThread* current, const char* filename) { _extra_interned_strings = new GrowableArrayCHeap(10000); diff --git a/src/hotspot/share/gc/shared/locationPrinter.inline.hpp b/src/hotspot/share/gc/shared/locationPrinter.inline.hpp index ae873d52cb5..bb79bf80a5b 100644 --- a/src/hotspot/share/gc/shared/locationPrinter.inline.hpp +++ b/src/hotspot/share/gc/shared/locationPrinter.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ bool BlockLocationPrinter::print_location(outputStream* st, void // Check if addr points into Java heap. bool in_heap = CollectedHeapT::heap()->is_in(addr); if (in_heap) { - // base_oop_or_null() might be unimplemented and return NULL for some GCs/generations + // base_oop_or_null() might be unimplemented and return null for some GCs/generations oop o = base_oop_or_null(addr); if (o != nullptr) { if ((void*)o == addr) { diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 73cc16bc122..015ec32700a 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -428,7 +428,7 @@ void ConstantPool::restore_unshareable_info(TRAPS) { assert(is_shared(), "should always be set for shared constant pools"); if (is_for_method_handle_intrinsic()) { // See the same check in remove_unshareable_info() below. - assert(cache() == NULL, "must not have cpCache"); + assert(cache() == nullptr, "must not have cpCache"); return; } assert(_cache != nullptr, "constant pool _cache should not be null"); @@ -474,7 +474,7 @@ void ConstantPool::remove_unshareable_info() { // This CP was created by Method::make_method_handle_intrinsic() and has nothing // that need to be removed/restored. It has no cpCache since the intrinsic methods // don't have any bytecodes. - assert(cache() == NULL, "must not have cpCache"); + assert(cache() == nullptr, "must not have cpCache"); return; } diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index 5474fef66da..bfa205e2fad 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -241,50 +241,40 @@ * * *

- * All native linker implementations support a well-defined subset of layouts. More formally, - * a layout {@code L} is supported by a native linker {@code NL} if: + * A native linker only supports function descriptors whose argument/return layouts are + * well-formed layouts. More formally, a layout `L` is well-formed if: *

    - *
  • {@code L} is a value layout {@code V} and {@code V.withoutName()} is a canonical layout
  • + *
  • {@code L} is a value layout and {@code L} is derived from a canonical layout + * {@code C} such that {@code L.byteAlignment() <= C.byteAlignment()}
  • *
  • {@code L} is a sequence layout {@code S} and all the following conditions hold: *
      - *
    1. the alignment constraint of {@code S} is set to its - * natural alignment, and
    2. - *
    3. {@code S.elementLayout()} is a layout supported by {@code NL}.
    4. + *
    5. {@code L.byteAlignment()} is equal to the sequence layout's natural alignment + * , and
    6. + *
    7. {@code S.elementLayout()} is a well-formed layout.
    8. *
    *
  • *
  • {@code L} is a group layout {@code G} and all the following conditions hold: *
      - *
    1. the alignment constraint of {@code G} is set to its - * natural alignment;
    2. - *
    3. the size of {@code G} is a multiple of its alignment constraint;
    4. - *
    5. each member layout in {@code G.memberLayouts()} is either a padding layout or - * a layout supported by {@code NL}, and
    6. - *
    7. {@code G} does not contain padding other than what is strictly required to align - * its non-padding layout elements, or to satisfy (2).
    8. + *
    9. {@code G.byteAlignment()} is equal to the group layout's natural alignment
    10. + *
    11. {@code G.byteSize()} is a multiple of {@code G.byteAlignment()}
    12. + *
    13. Each member layout in {@code G.memberLayouts()} is either a padding layout or a + * well-formed layout
    14. + *
    15. Each non-padding member layout {@code E} in {@code G.memberLayouts()} follows an + * optional padding member layout, whose size is the minimum size required to + * align {@code E}
    16. + *
    17. {@code G} contains an optional trailing padding member layout, whose size is the + * minimum size that satisfies (2)
    18. *
    *
  • *
- * - * Linker implementations may optionally support additional layouts, such as - * packed struct layouts. A packed struct is a struct in which there is - * at least one member layout {@code L} that has an alignment constraint less strict - * than its natural alignment. This allows to avoid padding between member layouts, - * as well as avoiding padding at the end of the struct layout. For example: - - * {@snippet lang = java: - * // No padding between the 2 element layouts: - * MemoryLayout noFieldPadding = MemoryLayout.structLayout( - * ValueLayout.JAVA_INT, - * ValueLayout.JAVA_DOUBLE.withByteAlignment(4)); - * - * // No padding at the end of the struct: - * MemoryLayout noTrailingPadding = MemoryLayout.structLayout( - * ValueLayout.JAVA_DOUBLE.withByteAlignment(4), - * ValueLayout.JAVA_INT); - * } *

- * A native linker only supports function descriptors whose argument/return layouts are - * layouts supported by that linker and are not sequence layouts. + * A function descriptor is well-formed if its argument and return layouts are + * well-formed and are not sequence layouts. A native linker is guaranteed to reject + * function descriptors that are not well-formed. However, a native linker can still + * reject well-formed function descriptors, according to platform-specific rules. + * For example, some native linkers may reject packed struct layouts -- struct + * layouts whose member layouts feature relaxed alignment constraints, to avoid + * the insertion of additional padding. * *

Function pointers

* diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java index 28391df7a0b..5b40ac17750 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java @@ -57,7 +57,6 @@ import java.lang.invoke.MethodType; import java.util.HashSet; import java.util.List; -import java.nio.ByteOrder; import java.util.Objects; import java.util.Set; @@ -189,6 +188,7 @@ private void checkLayoutRecursive(MemoryLayout layout) { checkHasNaturalAlignment(layout); long offset = 0; long lastUnpaddedOffset = 0; + PaddingLayout preceedingPadding = null; for (MemoryLayout member : sl.memberLayouts()) { // check element offset before recursing so that an error points at the // outermost layout first @@ -196,29 +196,65 @@ private void checkLayoutRecursive(MemoryLayout layout) { checkStructMember(member, offset); offset += member.byteSize(); - if (!(member instanceof PaddingLayout)) { + if (!(member instanceof PaddingLayout pl)) { lastUnpaddedOffset = offset; + if (preceedingPadding != null) { + preceedingPadding = null; + } + } else { + if (preceedingPadding != null) { + throw new IllegalArgumentException("The padding layout " + pl + + " was preceded by another padding layout " + preceedingPadding + + inMessage(sl)); + } + preceedingPadding = pl; } } - checkGroupSize(sl, lastUnpaddedOffset); + checkNotAllPadding(sl); + checkGroup(sl, lastUnpaddedOffset); } else if (layout instanceof UnionLayout ul) { checkHasNaturalAlignment(layout); - long maxUnpaddedLayout = 0; + // We need to know this up front + long maxUnpaddedLayout = ul.memberLayouts().stream() + .filter(l -> !(l instanceof PaddingLayout)) + .mapToLong(MemoryLayout::byteSize) + .max() + .orElse(0); + + boolean hasPadding = false; + for (MemoryLayout member : ul.memberLayouts()) { checkLayoutRecursive(member); - if (!(member instanceof PaddingLayout)) { - maxUnpaddedLayout = Long.max(maxUnpaddedLayout, member.byteSize()); + if (member instanceof PaddingLayout pl) { + if (hasPadding) { + throw new IllegalArgumentException("More than one padding" + inMessage(ul)); + } + hasPadding = true; + if (pl.byteSize() <= maxUnpaddedLayout) { + throw new IllegalArgumentException("Superfluous padding " + pl + inMessage(ul)); + } } } - checkGroupSize(ul, maxUnpaddedLayout); + checkGroup(ul, maxUnpaddedLayout); } else if (layout instanceof SequenceLayout sl) { checkHasNaturalAlignment(layout); + if (sl.elementLayout() instanceof PaddingLayout pl) { + throw memberException(sl, pl, + "not supported because a sequence of a padding layout is not allowed"); + } checkLayoutRecursive(sl.elementLayout()); } } - // check for trailing padding - private void checkGroupSize(GroupLayout gl, long maxUnpaddedOffset) { + // check elements are not all padding layouts + private static void checkNotAllPadding(StructLayout sl) { + if (!sl.memberLayouts().isEmpty() && sl.memberLayouts().stream().allMatch(e -> e instanceof PaddingLayout)) { + throw new IllegalArgumentException("Layout '" + sl + "' is non-empty and only has padding layouts"); + } + } + + // check trailing padding + private static void checkGroup(GroupLayout gl, long maxUnpaddedOffset) { long expectedSize = Utils.alignUp(maxUnpaddedOffset, gl.byteAlignment()); if (gl.byteSize() != expectedSize) { throw new IllegalArgumentException("Layout '" + gl + "' has unexpected size: " @@ -226,17 +262,28 @@ private void checkGroupSize(GroupLayout gl, long maxUnpaddedOffset) { } } + private static String inMessage(GroupLayout gl) { + return " in " + gl; + } + // checks both that there is no excess padding between 'memberLayout' and // the previous layout - private void checkMemberOffset(StructLayout parent, MemoryLayout memberLayout, + private static void checkMemberOffset(StructLayout parent, MemoryLayout memberLayout, long lastUnpaddedOffset, long offset) { long expectedOffset = Utils.alignUp(lastUnpaddedOffset, memberLayout.byteAlignment()); if (expectedOffset != offset) { - throw new IllegalArgumentException("Member layout '" + memberLayout + "', of '" + parent + "'" + - " found at unexpected offset: " + offset + " != " + expectedOffset); + throw memberException(parent, memberLayout, + "found at unexpected offset: " + offset + " != " + expectedOffset); } } + private static IllegalArgumentException memberException(MemoryLayout parent, + MemoryLayout member, + String info) { + return new IllegalArgumentException( + "Member layout '" + member + "', of '" + parent + "' " + info); + } + private void checkSupported(ValueLayout valueLayout) { valueLayout = valueLayout.withoutName(); if (valueLayout instanceof AddressLayout addressLayout) { diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java index 9fc9b64314c..60274d766cd 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -31,7 +31,6 @@ import java.awt.Dimension; import java.awt.Graphics; import java.awt.Insets; -import java.awt.KeyboardFocusManager; import java.awt.LayoutManager; import java.awt.Point; import java.awt.Rectangle; @@ -123,8 +122,6 @@ public class BasicScrollBarUI protected ArrowButtonListener buttonListener; /** Model listener */ protected ModelListener modelListener; - /** KeyboardFocusListener */ - protected KeyboardFocusListener keyboardFocusListener; /** Thumb rectangle */ protected Rectangle thumbRect; @@ -359,15 +356,12 @@ protected void installListeners(){ buttonListener = createArrowButtonListener(); modelListener = createModelListener(); propertyChangeListener = createPropertyChangeListener(); - keyboardFocusListener = createKeyboardFocusListener(); scrollbar.addMouseListener(trackListener); scrollbar.addMouseMotionListener(trackListener); scrollbar.getModel().addChangeListener(modelListener); scrollbar.addPropertyChangeListener(propertyChangeListener); scrollbar.addFocusListener(getHandler()); - KeyboardFocusManager.getCurrentKeyboardFocusManager() - .addPropertyChangeListener(keyboardFocusListener); if (incrButton != null) { incrButton.addMouseListener(buttonListener); @@ -449,8 +443,6 @@ protected void uninstallListeners() { incrButton.removeMouseListener(buttonListener); } - KeyboardFocusManager.getCurrentKeyboardFocusManager() - .removePropertyChangeListener(keyboardFocusListener); scrollbar.getModel().removeChangeListener(modelListener); scrollbar.removeMouseListener(trackListener); scrollbar.removeMouseMotionListener(trackListener); @@ -517,14 +509,6 @@ protected PropertyChangeListener createPropertyChangeListener() { return getHandler(); } - /** - * Creates a keyboard focus listener. - * @return a keyboard focus listener - */ - protected KeyboardFocusListener createKeyboardFocusListener() { - return new KeyboardFocusListener(); - } - private void updateThumbState(int x, int y) { Rectangle rect = getThumbBounds(); @@ -1218,35 +1202,6 @@ public boolean getSupportsAbsolutePositioning() { return supportsAbsolutePositioning; } - /** - * A listener to listen for keyboard focus changes. - */ - protected class KeyboardFocusListener implements PropertyChangeListener { - /** - * Constructs a {@code KeyboardFocusListener}. - */ - protected KeyboardFocusListener() {} - - @Override - public void propertyChange(PropertyChangeEvent e) { - String propertyName = e.getPropertyName(); - - if ("focusOwner" == propertyName) { - // Stop scrolling if no longer focus owner - if (e.getNewValue() == null && scrollTimer.isRunning()) { - scrollTimer.stop(); - buttonListener.handledEvent = false; - scrollbar.setValueIsAdjusting(false); - if (incrButton.getModel().isPressed()) { - incrButton.getModel().setPressed(false); - } else if (decrButton.getModel().isPressed()) { - decrButton.getModel().setPressed(false); - } - } - } - } - } - /** * A listener to listen for model changes. */ diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackPrintVMLocks.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackPrintVMLocks.java index ff1cc4b96bd..e46306cf8d3 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackPrintVMLocks.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackPrintVMLocks.java @@ -79,7 +79,10 @@ public static void main(String[] args) throws Exception { } throw new RuntimeException("Not able to find lock"); } finally { - theApp.getProcess().destroyForcibly(); + if (theApp.getProcess() != null) { + theApp.deleteLock(); + theApp.getProcess().destroyForcibly(); + } } } } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 90a6dc18e6d..63cfb2a338f 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -468,6 +468,7 @@ java/awt/Window/MainKeyWindowTest/TestMainKeyWindow.java 8265985 macosx-all java/awt/Robot/Delay/InterruptOfDelay.java 8265986 macosx-all java/awt/Robot/InfiniteLoopException.java 8342638 windows-all,linux-all java/awt/MenuBar/TestNoScreenMenuBar.java 8265987 macosx-all +java/awt/Robot/ScreenCaptureRobotTest.java 8344581 macosx-all java/awt/Graphics2D/DrawString/DrawRotatedStringUsingRotatedFont.java 8266283 generic-all java/awt/Graphics2D/DrawString/RotTransText.java 8316878 linux-all diff --git a/test/jdk/java/foreign/TestLinker.java b/test/jdk/java/foreign/TestLinker.java index 82d58300088..4bc19965f19 100644 --- a/test/jdk/java/foreign/TestLinker.java +++ b/test/jdk/java/foreign/TestLinker.java @@ -35,6 +35,9 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.PaddingLayout; +import java.lang.foreign.SequenceLayout; +import java.lang.foreign.StructLayout; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.util.ArrayList; @@ -42,12 +45,8 @@ import java.util.List; import static java.lang.foreign.MemoryLayout.*; -import static java.lang.foreign.ValueLayout.JAVA_CHAR; -import static java.lang.foreign.ValueLayout.JAVA_SHORT; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertSame; -import static org.testng.Assert.assertNotSame; -import static org.testng.Assert.assertTrue; +import static java.lang.foreign.ValueLayout.*; +import static org.testng.Assert.*; public class TestLinker extends NativeTestHelper { @@ -150,6 +149,110 @@ public void testCanonicalLayouts(String typeName) { assertTrue(layout instanceof ValueLayout); } + @Test + public void embeddedPaddingLayout() { + PaddingLayout padding = MemoryLayout.paddingLayout(64).withByteAlignment(64); + SequenceLayout sequence = MemoryLayout.sequenceLayout(2, padding); + StructLayout struct = MemoryLayout.structLayout(sequence); + FunctionDescriptor fd = FunctionDescriptor.of(struct, struct); + Linker linker = Linker.nativeLinker(); + var x = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertTrue(x.getMessage().contains("not supported because a sequence of a padding layout is not allowed")); + } + + @Test + public void groupLayoutWithOnlyPadding() { + PaddingLayout padding = MemoryLayout.paddingLayout(1); + StructLayout struct = MemoryLayout.structLayout(padding); + FunctionDescriptor fd = FunctionDescriptor.of(struct, struct); + Linker linker = Linker.nativeLinker(); + var x = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertTrue(x.getMessage().contains("is non-empty and only has padding layouts")); + } + + @Test + public void interwovenPadding() { + Linker linker = Linker.nativeLinker(); + var padding1 = MemoryLayout.paddingLayout(1); + var padding2 = MemoryLayout.paddingLayout(2).withByteAlignment(2); + + var struct = MemoryLayout.structLayout(JAVA_BYTE, padding1, padding2, JAVA_INT); + + var fd = FunctionDescriptor.of(struct, struct, struct); + var e = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals(e.getMessage(), + "The padding layout x2 was preceded by another padding layout x1 in [b1x1x2i4]"); + } + + @Test + public void stackedPadding() { + Linker linker = Linker.nativeLinker(); + var struct32 = MemoryLayout.structLayout(MemoryLayout.sequenceLayout(4, JAVA_LONG)); + var padding1 = MemoryLayout.paddingLayout(1); + var padding2 = MemoryLayout.paddingLayout(2).withByteAlignment(2); + var padding4 = MemoryLayout.paddingLayout(4).withByteAlignment(4); + var padding8 = MemoryLayout.paddingLayout(8).withByteAlignment(8); + var padding16 = MemoryLayout.paddingLayout(16).withByteAlignment(16); + var padding32 = MemoryLayout.paddingLayout(32).withByteAlignment(32); + var union = MemoryLayout.unionLayout(struct32, padding32); + var struct = MemoryLayout.structLayout(JAVA_BYTE, padding1, padding2, padding4, padding8, padding16, union); + var fd = FunctionDescriptor.of(struct, struct, struct); + var e = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals(e.getMessage(), + "The padding layout x2 was preceded by another padding layout x1 in [b1x1x2x4x8x16[[[4:j8]]|x32]]"); + } + + @Test + public void paddingUnionByteSize3() { + Linker linker = Linker.nativeLinker(); + var union = MemoryLayout.unionLayout(MemoryLayout.paddingLayout(3), ValueLayout.JAVA_INT); + var fd = FunctionDescriptor.of(union, union, union); + var e = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals(e.getMessage(), "Superfluous padding x3 in [x3|i4]"); + } + + @Test + public void paddingUnionByteSize4() { + Linker linker = Linker.nativeLinker(); + var union = MemoryLayout.unionLayout(MemoryLayout.paddingLayout(4), ValueLayout.JAVA_INT); + var fd = FunctionDescriptor.of(union, union, union); + var e = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals(e.getMessage(), "Superfluous padding x4 in [x4|i4]"); + } + + @Test + public void paddingUnionByteSize5() { + Linker linker = Linker.nativeLinker(); + var union = MemoryLayout.unionLayout(MemoryLayout.paddingLayout(5), ValueLayout.JAVA_INT); + var fd = FunctionDescriptor.of(union, union, union); + var e = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals(e.getMessage(), "Layout '[x5|i4]' has unexpected size: 5 != 4"); + } + + @Test + public void paddingUnionSeveral() { + Linker linker = Linker.nativeLinker(); + var union = MemoryLayout.unionLayout( + MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT), + ValueLayout.JAVA_LONG, + MemoryLayout.paddingLayout(16), + MemoryLayout.paddingLayout(16)); + var fd = FunctionDescriptor.of(union, union, union); + var e = expectThrows(IllegalArgumentException.class, () -> linker.downcallHandle(fd)); + assertEquals(e.getMessage(), "More than one padding in [[3:i4]|j8|x16|x16]"); + } + + @Test + public void sequenceOfZeroElements() { + Linker linker = Linker.nativeLinker(); + var sequence0a8 = MemoryLayout.sequenceLayout(0, JAVA_LONG); + var sequence3a1 = MemoryLayout.sequenceLayout(3, JAVA_BYTE); + var padding5a1 = MemoryLayout.paddingLayout(5); + var struct8a8 = MemoryLayout.structLayout(sequence0a8, sequence3a1, padding5a1); + var fd = FunctionDescriptor.of(struct8a8, struct8a8, struct8a8); + linker.downcallHandle(fd); + } + @DataProvider public static Object[][] canonicalTypeNames() { return new Object[][]{ diff --git a/test/jdk/javax/swing/JComboBox/JComboBoxScrollFocusTest.java b/test/jdk/javax/swing/JComboBox/JComboBoxScrollFocusTest.java deleted file mode 100644 index 4d2c3bd19cc..00000000000 --- a/test/jdk/javax/swing/JComboBox/JComboBoxScrollFocusTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import javax.swing.JComboBox; -import javax.swing.JFrame; - -/* - * @test - * @bug 6672644 - * @library /java/awt/regtesthelpers - * @build PassFailJFrame - * @summary Tests JComboBox scrollbar behavior when alt-tabbing - * @requires os.family != "mac" - * @run main/manual JComboBoxScrollFocusTest - */ - -public class JComboBoxScrollFocusTest { - private static final String INSTRUCTIONS = - """ - Click on the dropdown button for the JComboBox in the test frame. - Then, press and hold the left click button on the down arrow button - in the popup list. While holding the left click button, the list - should be scrolling down. Press ALT + TAB while holding down the - left click to switch focus to a different window. Then release the - left click button. Focus the test frame again and click the - dropdown button for the JComboBox again. The list should be - stationary and not be automatically scrolling. - - If you are able to execute all steps successfully then the test - passes, otherwise it fails. - """; - - public static void main(String[] args) throws Exception { - PassFailJFrame - .builder() - .title("JComboBoxScrollFocusTest Test Instructions") - .instructions(INSTRUCTIONS) - .columns(40) - .testUI(JComboBoxScrollFocusTest::createAndShowGUI) - .build() - .awaitAndCheck(); - } - - private static JFrame createAndShowGUI() { - JFrame frame = new JFrame("JComboBoxScrollFocusTest Test Frame"); - JComboBox combobox = new JComboBox<>(); - for (int i = 0; i < 100; i++) { - combobox.addItem(String.valueOf(i)); - } - frame.add(combobox); - frame.setSize(400, 200); - frame.setLocationRelativeTo(null); - return frame; - } -}